home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr25 / mklapi10.zip / MKLAPI.DOC < prev    next >
Text File  |  1993-05-04  |  116KB  |  2,878 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13.  
  14.  
  15.  
  16.                                                                              
  17.  
  18.                                                                        MKLAPI
  19.                                                                              
  20.                                                  Märklin-Interface driver and
  21.                                                           High Level Language
  22.                                             Application Programming Interface
  23.                                                      for C-language and BASIC
  24.                                                                   Version 1.0
  25.                                                                              
  26.  
  27.  
  28.  
  29.                                                 Document Number RH-MKLAPI 1.0
  30.  
  31.                                                                   May 4, 1993
  32.  
  33.  
  34.                                                                 Rob Hamerling
  35.  
  36.                                                                     Vianen-ZH
  37.                                                               The Netherlands
  38.                                                  Phone: 31-3473-72136 (voice)
  39.                                                            FIDO: 2:512/4.1098
  40.  
  41.                                                                        MKLAPI
  42.  
  43.  
  44.  
  45.   MKLAPI
  46.   ───────────────────────────────────────────────────────────────────────────
  47.   
  48.   
  49.   CONTENTS
  50.  
  51.  
  52.     Introduction  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
  53.     What is MKLAPI?   . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
  54.     Purpose   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
  55.     Realisation   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
  56.     Registration  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
  57.  
  58.     Functional description  . . . . . . . . . . . . . . . . . . . . . . . . 3
  59.     Overview  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
  60.     Terminology   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
  61.     Functional Requirements   . . . . . . . . . . . . . . . . . . . . . . . 3
  62.     Provided Facilities   . . . . . . . . . . . . . . . . . . . . . . . . . 4
  63.     Deliverables  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
  64.     Prerequisites   . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
  65.     Restrictions and Limitations  . . . . . . . . . . . . . . . . . . . . . 5
  66.     Tests   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
  67.     C-language framework  . . . . . . . . . . . . . . . . . . . . . . . . . 7
  68.     QuickBASIC framework  . . . . . . . . . . . . . . . . . . . . . . . . . 8
  69.     Sample programs   . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
  70.     OS/2 and DOS differences   . . . . . . . . . . . . . . . . . . . . . . 10
  71.  
  72.     Specifications   . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
  73.     Available Functions  . . . . . . . . . . . . . . . . . . . . . . . . . 11
  74.     mklclose   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
  75.     mklflush   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
  76.     mklgetsn   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
  77.     mklgo  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
  78.     mklmsecs   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
  79.     mklopen  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
  80.     mklpoll  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
  81.     mklpurge   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
  82.     mklputc  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
  83.     mklsleep   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
  84.     mklsound   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
  85.     mklstats   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
  86.     mklstop  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
  87.     mkltime  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
  88.     mkltrace   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
  89.     Macro Specifications   . . . . . . . . . . . . . . . . . . . . . . . . 23
  90.       mklput1c   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
  91.       mklput2c   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
  92.     Use of timer   . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
  93.     QuickBASIC Function Specifications   . . . . . . . . . . . . . . . . . 25
  94.     Errors and Signals   . . . . . . . . . . . . . . . . . . . . . . . . . 25
  95.  
  96.     Installation   . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
  97.     Application development considerations   . . . . . . . . . . . . . . . 27
  98.     C-Compiler considerations  . . . . . . . . . . . . . . . . . . . . . . 27
  99.     MicroSoft QuickBASIC compiler 4.5 Considerations   . . . . . . . . . . 27
  100.     Building an EXE-file   . . . . . . . . . . . . . . . . . . . . . . . . 27
  101.       C-language and DOS   . . . . . . . . . . . . . . . . . . . . . . . . 28
  102.       C-language and BASIC   . . . . . . . . . . . . . . . . . . . . . . . 28
  103.       C-language and OS2 1.3   . . . . . . . . . . . . . . . . . . . . . . 29
  104.  
  105.   ───────────────────────────────────────────────────────────────────────────
  106.                                                                  Contents  ii
  107.  
  108.   MKLAPI
  109.   ───────────────────────────────────────────────────────────────────────────
  110.   
  111.   
  112.       C-language and OS2 2.0+  . . . . . . . . . . . . . . . . . . . . . . 30
  113.     Storage and performance  . . . . . . . . . . . . . . . . . . . . . . . 30
  114.       Memory Utilisation   . . . . . . . . . . . . . . . . . . . . . . . . 30
  115.       Processor utilisation  . . . . . . . . . . . . . . . . . . . . . . . 30
  116.     Comments, Remarks, Bug-reports   . . . . . . . . . . . . . . . . . . . 31
  117.  
  118.     Appendix A.  MKLAPI Internals  . . . . . . . . . . . . . . . . . . . . 32
  119.     Multitasking   . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
  120.     Reading Märklin S88 encoders   . . . . . . . . . . . . . . . . . . . . 33
  121.     Communications Interface Specification   . . . . . . . . . . . . . . . 35
  122.     Problems with OS/2 COM[xx].SYS   . . . . . . . . . . . . . . . . . . . 37
  123.     OS/2 and DOS differences   . . . . . . . . . . . . . . . . . . . . . . 38
  124.  
  125.     Appendix B.  Trace facility  . . . . . . . . . . . . . . . . . . . . . 40
  126.     Trace records  . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
  127.     Sample   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
  128.  
  129.   | Appendix C.  Märklin-Interface peculiarities   . . . . . . . . . . . . 41
  130.  
  131.     Appendix D.  Summary of changes  . . . . . . . . . . . . . . . . . . . 42
  132.  
  133.  
  134.  
  135.  
  136.  
  137.  
  138.  
  139.  
  140.  
  141.  
  142.  
  143.  
  144.  
  145.  
  146.  
  147.  
  148.  
  149.  
  150.  
  151.  
  152.  
  153.  
  154.  
  155.  
  156.  
  157.  
  158.  
  159.  
  160.  
  161.  
  162.  
  163.  
  164.   
  165.   ────────────────────
  166.   (1)     This document is processed: on May 4, 1993 at 9:52 p.m.
  167.  
  168.   ───────────────────────────────────────────────────────────────────────────
  169.                                                                 Contents  iii
  170.  
  171.   MKLAPI
  172.   ───────────────────────────────────────────────────────────────────────────
  173.   
  174.   
  175.   INTRODUCTION
  176.  
  177.                     Copyright (C) R. Hamerling, 1991, 1993
  178.                              All Rights Reserved.
  179.   
  180.  
  181.  
  182.  
  183.   WHAT IS MKLAPI?
  184.  
  185.   MKLAPI is a combination of:
  186.  
  187.   ■  a driver for buffered communications, automatic reading of Märklin S88
  188.      encoder-boxes, timer- and some other services.
  189.  
  190.   ■  a number of user callable routines for common elementary functions, with
  191.      a comfortable high-level programming interface.
  192.  
  193.   So MKLAPI reliefs a programmer from 'low-level' tasks such as controlling
  194.   the communication with the Märklin-Interface, so that he can concentrate on
  195.   the railroad-control logic.  This simplifies programming for
  196.   model-railroads which are controlled via a Märklin-Interface.  Internally
  197.   it performs a kind of multi-tasking, which is highly desirable for this
  198.   realtime environment ('proces control').
  199.  
  200.  
  201.   PURPOSE
  202.  
  203.   The driver and API has been developed for the following purposes:
  204.  
  205.   ■  have an application programming interface (API) which is independent of
  206.      the operating system (i.c. OS/2 or DOS).
  207.  
  208.   ■  provide a simple interface for a number of frequently used basic control
  209.      functions such as sending commands to trains and switch points, and
  210.      reading sensors.
  211.  
  212.   ■  allow the mainline to be written completely in high-level programming
  213.      language (i.c. C-language or QuickBASIC).
  214.  
  215.   ■  obtain a buffered communications facility to the Märklin-Interface,
  216.      including automatic flow control as required by the Märklin-Interface.
  217.  
  218.   ■  have 'background' tasks for a number of functions that should or could
  219.      be performed independently and asynchronously from the mainline.
  220.  
  221.   ■  provide an accurate and efficient timer facility for time-dependent
  222.      operations, events and interval-calculations.
  223.  
  224.  
  225.  
  226.  
  227.  
  228.  
  229.  
  230.  
  231.   ───────────────────────────────────────────────────────────────────────────
  232.                                                               Introduction  1
  233.  
  234.   MKLAPI
  235.   ───────────────────────────────────────────────────────────────────────────
  236.   
  237.   
  238.   REALISATION
  239.  
  240.   This package offers a set of drivers with all the functionality of listed
  241.   "Purpose" on page 1.  Although the OS/2-drivers and DOS-drivers are
  242.   completely different implementations, due to the rather extreme differences
  243.   in functionality provided by OS/2 and DOS for this type of environment, the
  244.   mainline of your railroad control program may be unaware of the underlying
  245.   operating system: the application programming interface is identical.
  246.  
  247.   You may read a number of minor differences in "OS/2 and DOS differences" on
  248.   page 10.
  249.  
  250.  
  251.   REGISTRATION
  252.  
  253.   This package is of the 'SHAREWARE' type: You may try it for a reasonably
  254.   short time (max 3 months).  If you decide to use it for your own railroad
  255.   control program, you may show your appreciation and become a 'registered
  256.   user'.  After registration, I'll send you by mail:
  257.  
  258.   ■  A diskette (3-1/2", 720KB), with the following contents:
  259.      ∙  The most recent version of all the drivers.
  260.      ∙  Source-files (C-language) of a couple of sample programs provided as
  261.         executables in the base package.
  262.  
  263.   ■  Complete and up-to-date printed documentation, as well as 2
  264.      documentation files on the diskette:
  265.      ∙  A print-file, formatted for IBM Pro-Printer III.
  266.      ∙  A file in OS/2 INF format (VIEW-able as online documentation like the
  267.         inline OS/2 Command Reference Manual).
  268.  
  269.   After registration you are allowed to distribute the driver as integral
  270.   part of your own railroad control application programs.  The package (not
  271.   the material you get after registration) may be distributed freely with
  272.   under the following conditions:
  273.  
  274.   ■  it remains a separate and complete package
  275.   ■  you do not apply changes of any kind
  276.   ■  you do not make profit with it
  277.  
  278.   The registration fee is 45 Dutch Guilders or equivalent of 25 US-Dollars.
  279.   Bare money is accepted as well, but foreign money only in the form of
  280.   US-Dollar banknotes.
  281.  
  282.   Please send your comments and registration fee to:
  283.  
  284.        R. Hamerling
  285.        Vianen-ZH,
  286.        The Netherlands
  287.        Postbank acct#: 2087285
  288.        PC-Square: FIDOnet 2:512/4.1098
  289.  
  290.   Mention the purpose of your payment ("MKLAPI"), and the destination
  291.   address!  MKLAPI-source is not included.
  292.  
  293.  
  294.   ───────────────────────────────────────────────────────────────────────────
  295.                                                               Introduction  2
  296.  
  297.   MKLAPI
  298.   ───────────────────────────────────────────────────────────────────────────
  299.   
  300.   
  301.   FUNCTIONAL DESCRIPTION
  302.  
  303.   This chapter describes a possible use of this package.
  304.  
  305.  
  306.   OVERVIEW
  307.  
  308.   The Märklin-Interface-driver package is a set of functions to enable direct
  309.   communications support in a program written in C-language or BASIC for the
  310.   MicroSoft QuickBASIC compiler 4.5((2)) for the family of IBM Personal
  311.   System/2 and compatibles.
  312.   Please report problems with the driver as soon as you can.  and accompany
  313.   your report with as much details as might be relevant.
  314.  
  315.  
  316.   TERMINOLOGY
  317.  
  318.   In this document I use a number of terms which should probably be clarified
  319.   first.
  320.  
  321.   Interface The Märklin-Interface. (Märklin partnumber 6050)
  322.  
  323.   Sensor    The Märklin S88 encoder. (Märklin partnumber 6088).  Sometimes
  324.             also called sensor-box or encoder.
  325.  
  326.   Switch    The railroad facility, Märklin K83 decoder (Märklin partnumber
  327.             6083) is used to control these switch points.
  328.  
  329.  
  330.  
  331.   FUNCTIONAL REQUIREMENTS
  332.  
  333.   The Märklin-Interface-driver must provide the following functionality:
  334.  
  335.   ■  Possibility to send commands to the Märklin-Interface in any sequence
  336.      and mix.
  337.  
  338.   ■  Builtin buffered communication with the Märklin-Interface.
  339.  
  340.   ■  Automatic flow control between PC and Märklin-Interface.
  341.  
  342.   ■  Time-base (clock) for for time-dependent control, independent of
  343.      hardware (processor) speed.
  344.  
  345.   ■  Automatic readout of sensor-boxes (Märklin S88 encoder): the mainline
  346.      must be able to obtain sensor positions instantaneously (without
  347.      waittime).
  348.  
  349.   
  350.   ────────────────────
  351.   (2)     Please note that this driver is delivered in the form of
  352.           .OBJ-files, and therefore can be used only with compiled programs
  353.           (other .OBJ-files).  QBASIC that comes with DOS 5.0 is not capable
  354.           of producing an .OBJ file, you'll need the MicroSoft QuickBASIC
  355.           compiler 4.5 to use this driver with BASIC programs.
  356.  
  357.   ───────────────────────────────────────────────────────────────────────────
  358.                                                     Functional description  3
  359.  
  360.   MKLAPI
  361.   ───────────────────────────────────────────────────────────────────────────
  362.   
  363.   
  364.   ■  Priority mechanism: mainline activities must be handled with higher
  365.      priority than 'background' service processes.
  366.  
  367.   ■  Ability for emergency stops, regardless of the state of the program or
  368.      the model railroad.
  369.  
  370.  
  371.  
  372.   PROVIDED FACILITIES
  373.  
  374.   To fulfil the functional requirements, a 'driver' has been built.  It
  375.   contains a number of service-routines (and for DOS also hardware interrupt
  376.   routines), and provides the following facilities:
  377.  
  378.   ■  Functions to send train and switch commands to the interface.
  379.  
  380.      Two macro's for output of resp. 1 or 2 consecutive characters (the so
  381.      called 1-byte or 2-byte commands).  With the 2-byte form the subroutines
  382.      ensure that the 2 characters are sent as 2 consecutive characters (not
  383.      interrupted by a 'background' task).
  384.  
  385.   ■  Functions to read sensors (S88-boxes).
  386.  
  387.      This can either be done by immediate reading the status of the last
  388.      polling operation (if polling started).  "Reading Märklin S88 encoders"
  389.      on page 33 contains details about this mechanism.
  390.  
  391.      If the mainline is sending a command to the Märklin-Interface, polling
  392.      is automatically suspended (the command is treated with higher
  393.      priority).
  394.  
  395.   ■  A 'shadow' of the system timer, but expressed in milliseconds since
  396.      program start.  This timer has with the OS/2-driver of MKLAPI a
  397.      precision of 31.25 msecs, using standard OS/2 facilities (the timer
  398.      tick).  With the DOS-driver of MKLAPI the posibilities of the hardware
  399.      PC timer are explored, giving a precision of 1 millisecond.
  400.  
  401.   ■  A trace facility is built in for easy program debugging.  All output to
  402.      the interface can [optionally] be traced (OS/2 only) and formatted
  403.      later.
  404.  
  405.  
  406.  
  407.   DELIVERABLES
  408.  
  409.   The shareware components of the Märklin-Interface-driver package are:
  410.  
  411. | ■  This documentation file: MKLAPI.DOC.
  412. | ■  Header file for C-language: MKLAPI.H with function prototypes, data- and
  413. |    macro- definitions.
  414. | ■  Include file for QuickBASIC: MKLAPI.INC with function prototypes.
  415. | ■  2 OS/2-object decks, MKLAPI2.OBJ (16-bits OS/2 version) and MKLAPI3.OBJ
  416. |    (32-bits OS/2 version), with a buffered multitasking communication
  417. |    interface, polling, timer-support and trace facility.
  418. | ■  2 DOS-object decks for C-language programs, SMKLAPI.OBJ and LMKLAPI.OBJ,
  419.  
  420.   ───────────────────────────────────────────────────────────────────────────
  421.                                                     Functional description  4
  422.  
  423.   MKLAPI
  424.   ───────────────────────────────────────────────────────────────────────────
  425.   
  426.   
  427. |    with the same functionality as the OS/2 drivers, (but without a trace
  428. |    facility).  SMKLAPI is the object deck to be linked with your SMALL
  429. |    memory model program, LMKLAPI.OBJ is for LARGE memory model C-language
  430. |    programs.  LMKLAPI.OBJ is also used for QuickBASIC programs.
  431.   ■  TRAIN.EXE and TRAIN2.EXE, which are ready to run sample programs for a
  432.      DOS and OS/2 environment respectively.  See "Sample programs" on page 8
  433.      for some characteristics of these programs.
  434.   ■  MKLTRFMT.EXE, utility to interpret (format) the recorded trace file.
  435.  
  436.   The registration package consists of:
  437.  
  438.   ■  Sources (in C-language) of a sample train control program that makes use
  439.      of the Märklin driver, usable for OS/2 and DOS ('fullscreen'
  440.      application)
  441.   ■  All include and header files
  442.   ■  All MAKE and DEF files, used for compilation with MicroSoft C-compiler
  443.      6.00a or equivalent, IBM C SET/2 compiler for 32-bits programs and
  444.      MicroSoft QuickBASIC compiler 4.5 for QuickBASIC programs.
  445.  
  446.  
  447.  
  448.   PREREQUISITES
  449.  
  450.   The package has been built with the following assumptions:
  451.  
  452.   ■  Your PC-hardware is 100% compatible with the productline of IBM Personal
  453.      Computers (PC, PC/XT, PC/AT, and all current models of the Personal
  454.      System/2 family), in particular the asynchronous communication adapters,
  455.      their port addresses, etc. and the hardware timer.
  456.  
  457.   ■  The operating system is either OS/2 1.2 or higher, or PC-DOS 2.1 or
  458.      MS-DOS 2.1 or higher.  The package has been tested only with IBM PC/DOS
  459.      version 4.0 and 5.0, and with OS/2 version 1.3 and 2.0 (in OS/2
  460.      session).
  461.  
  462.   ■  Your (16-bits) C-programs (OS/2 and DOS) will be compiled with MicroSoft
  463.      C-compiler 6.00a.  For 32-bits C-programs IBM C SET/2 compiler is
  464.      assumed.  There may be some specific requirements on system hardware and
  465.      software for these.  Maybe Borland Turbo C compiler will work as well,
  466.      but this has not been tested.
  467.  
  468.   ■  Your BASIC programs will be compiled with the MicroSoft QuickBASIC
  469.      compiler 4.5.
  470.  
  471.  
  472.  
  473.   RESTRICTIONS AND LIMITATIONS
  474.  
  475.   The following restrictions apply:
  476.  
  477.   ■  One single port can be used between open and close of the COM-port to
  478.      the Märklin-Interface, all other functions apply to the port chosen at
  479.      open-time.
  480.  
  481.   ■  The transmit buffer of the DOS-driver is 2048 bytes long, for OS/2 it
  482.  
  483.   ───────────────────────────────────────────────────────────────────────────
  484.                                                     Functional description  5
  485.  
  486.   MKLAPI
  487.   ───────────────────────────────────────────────────────────────────────────
  488.   
  489.   
  490.      depends on COM[xx].SYS, or substitute.
  491.  
  492.   ■  Received data is transferred immediately to the sensor-array (64 bytes).
  493.  
  494.   ■  When the mainline is sending data to the Märklin-Interface and a
  495.      buffer-full situation arises, the data will be discarded.  However it is
  496.      very unlikely that this will happen in real life.
  497.  
  498.   ■  If you read a sensor-box outside the polling-range, the response is
  499.      undefined.
  500.  
  501.  
  502.  
  503.   TESTS
  504.  
  505.   The drivers have been tested by the author with combinations of the
  506.   following hardware and software:
  507.  
  508.   ■  model railroad equipment:
  509.      ∙  Märklin Combined Control
  510.      ∙  3 Märklin Digital locs
  511.      ∙  3 Märklin K83 decoders, each connected to 4 switch points
  512.      ∙  1 Märklin S88 encoder, with railroad-section sensoring
  513.  
  514.   ■  computer hardware:
  515.      ∙  IBM PC/AT-3 (80286/8) with IBM serial-parallel adapter
  516.      ∙  IBM PS/2 model 80 (80386/16) with standard serial port
  517.      ∙  IBM PS/2 notebook N51SLC (80386SLC/16) with standard serial port and
  518.         second serial port
  519.      ∙  IBM compatible 80486/33 with multi-I/O card
  520.  
  521.      Note: The DOS-drivers are written in 8086/8 Assembler and should also
  522.      work on XT-type systems.
  523.  
  524.   ■  Operation Systems:
  525. |    ∙  IBM OS/2 2.0: 32-bits mode with MKLAPI3.OBJ, 16-bits mode with
  526. |       MKLAPI2.OBJ, DOS-session with LMKLAPI.OBJ
  527. |    ∙  IBM OS/2 1.3: MKLAPI2.OBJ
  528. |    ∙  IBM PC/DOS 5.0: LMKLAPI.OBJ with QuickBASIC and C-language
  529.  
  530.   Note: Not all combinations of hardware and software have been tested, but
  531.   it is not likely that any viable combination will not work.
  532.  
  533.  
  534.  
  535.  
  536.  
  537.  
  538.  
  539.  
  540.  
  541.  
  542.  
  543.  
  544.  
  545.  
  546.   ───────────────────────────────────────────────────────────────────────────
  547.                                                     Functional description  6
  548.  
  549.   MKLAPI
  550.   ───────────────────────────────────────────────────────────────────────────
  551.   
  552.   
  553.   C-LANGUAGE FRAMEWORK
  554.  
  555.   A typical model railroad control program with this driver may look like:
  556.  
  557.  
  558.        #include "mklapi.h"
  559.  
  560.        mklopen(1,2400);                  /* open COM1: */
  561.        mklpoll(5);                       /* 5 S88 boxes in yard */
  562.        while (key != ESC) {              /* end program from keyboard */
  563.          if (kbhit()) {                  /* keyboard input */
  564.            if (key = getch()) {          /* normal key (incl alt-numpad) */
  565.              switch(key) {
  566.                case '?':   - - - - -     /* your key, your function */
  567.                            break;
  568.                case ESC:   break;        /* nothing now, exit program */
  569.                default:    fprintf(stdout,"%c",BEL);
  570.                            break;        /* unsupported normal key */
  571.                }
  572.              }
  573.            else {                        /* 'special' key */
  574.              switch(key = getch()) {     /* extended character */
  575.                case PgDn:   - - - - -    /* your 'extended' key function */
  576.                            break;
  577.                default:    fprintf(stdout,"%c",BEL);
  578.                            break;        /* unsupported 'extended' key */
  579.                }
  580.              }
  581.            }
  582.          for (i=0; i<MAXTRAIN; i++) {    /* scan train matrix */
  583.            - - - - -                     /* train control function */
  584.            }
  585.          for (i=1; i<5, ++i) {           /* scan S88 boxes */
  586.            mklgetsn(i);                  /* read sensor bits */
  587.            - - - - - -                   /* process changes */
  588.            }
  589.          if (!(mkltime()%5000)) {        /* every 5 seconds */
  590.            - - - - -                     /* anything else */
  591.            }
  592.          mklsleep(25);                   /* give up remainder of timeslice */
  593.          }
  594.        mklflush();                       /* wait until output sent */
  595.        mklclose();                       /* terminate */
  596.  
  597.   Note: Above code is just a framework to show the general setup of a model
  598.   railroad control program using the Märklin-Interface.
  599.  
  600.  
  601.  
  602.  
  603.  
  604.  
  605.  
  606.  
  607.  
  608.  
  609.   ───────────────────────────────────────────────────────────────────────────
  610.                                                     Functional description  7
  611.  
  612.   MKLAPI
  613.   ───────────────────────────────────────────────────────────────────────────
  614.   
  615.   
  616.   QUICKBASIC FRAMEWORK
  617.  
  618.   An equivalent framework in QuickBASIC might look like:
  619.  
  620.  
  621.        ' $INCLUDE: 'MRKAPI.INC'
  622.  
  623.        rc = mklopen(1,2400);
  624.        mklpoll(5);
  625.        key$ = INKEY$
  626.        while key$ <> ESC$
  627.          select case key$
  628.            case '?'
  629.               - - - - -
  630.            case ESC
  631.               - - - - -
  632.            case else
  633.              print "error key"
  634.          end select
  635.          for i=0 to MAXTRAIN
  636.            - - - - -
  637.          next i
  638.          for i=1 to 5
  639.            mklgetsn(i)
  640.            - - - - - -
  641.          next i
  642.          if MOD(mkltime,5000) < 50 then
  643.            - - - - -
  644.          end if
  645.          mklsleep(25)
  646.          key$ = INKEY$
  647.        wend
  648.        mklflush;
  649.        mklclose;
  650.  
  651.   Note: This code may not be true and workable QuickBASIC!
  652.  
  653.   The file MKLAPI.INC contains the DECLARE lines for all functions contained
  654.   in LMKLAPI.OBJ.  It should be included in a QuickBASIC program to obtain
  655.   the correct calling conventions and activates syntax checking by the
  656.   MicroSoft QuickBASIC compiler 4.5.  Subsequently the file LMKLAPI.OBJ
  657.   should be linked with your QuickBASIC program to include the MKLAPI
  658.   functions and subroutines.
  659.  
  660.  
  661.   SAMPLE PROGRAMS
  662.  
  663.   After registration you will receive the sources a sample (C-language)
  664.   program:
  665.  
  666.   ■  Control of 8 trains and several other possibilities, with the following
  667.      details:
  668.      ∙  Speed is controlled from the computer keyboard with arrow (cursor)
  669.         keys: right-key is faster, left-key is slower, up-key is maximum for
  670.         this train, down is maximum backward for this train.
  671.  
  672.   ───────────────────────────────────────────────────────────────────────────
  673.                                                     Functional description  8
  674.  
  675.   MKLAPI
  676.   ───────────────────────────────────────────────────────────────────────────
  677.   
  678.   
  679.      ∙  The train for which the command is meant is selected with a
  680.         number-key (program provides control for trains 1 through 8).  The
  681.         corresponding loc-address and other train properties are in a matrix
  682.         (with individual entries for each train), such as minimum and maximum
  683.         speed in Märklin Central Control values.  The train addresses that
  684.         are programmed are 10 for train 1, 20 for train 2, etc until 80 for
  685.         train 8.
  686.      ∙  The speed-control is indirect: you tell the system the program
  687.         loc-speed, the program does mass-simulation ('slow' increase and
  688.         decrease of speed).  The parameters for enertia simulation are part
  689.         of the train definitions.
  690.      ∙  For each train its address, desired and actual train speed are
  691.         displayed (in color).  Direction changes are buffered and automatic.
  692.      ∙  The display also indicates direction and whether the extra function
  693.         is 'on' or 'off'.
  694.  
  695.   ■  Control of 4 Märklin K83 decoder for 16 railroad switch points.  For
  696.      each switch the position ('normal' or 'bound' in color) and its address
  697.      is displayed.  The keys are A-P for adresses 253-256, and 1-12
  698.      respectively.
  699.  
  700.   ■  Polling of Märklin S88 encoder each with 16 sensors (or isolated
  701.      railroad sections).  The position is displayed real time, nothing but
  702.      displaying is done with the information.  2 Märklin S88 encoder-boxes
  703.      are being polled.
  704.  
  705.   ■  Sensor 16 of Märklin S88 encoder-box 1 is designated for speed
  706.      measurement.  The display shows the time (in milliseconds) between 2
  707.      successive 'OFF-ON' transitions.  If there is 1 train running and moving
  708.      along the same road, this facility can be used for calibrating speed
  709.      calculations for each speed-command-value.
  710.  
  711.   ■  Other keys:
  712.      Insert    Set Function 'on'
  713.      Delete    Set Function 'off'
  714.      End       Stop polling
  715.      Home      Restart polling
  716.      F3        Stop the program (has to be entered twice consecutively)
  717.      Esc       Emergency Stop (issues the Märklin Central Control STOP
  718.                command)
  719.      Enter     Resume (issues the Märklin Central Control GO command)
  720.  
  721.   The program may be started with 2 numeric parameters:
  722.  
  723.   1. the first parameter indicates the COM-port to be used (1 for COM1, 2 for
  724.      COM2, etc.), The default is COM1.
  725.   2. The second parameter indicates the number of Märklin S88 encoder-boxes
  726.      to include in the polling mechanism.  The default is 2.
  727.  
  728.  
  729.  
  730.  
  731.  
  732.  
  733.  
  734.  
  735.   ───────────────────────────────────────────────────────────────────────────
  736.                                                     Functional description  9
  737.  
  738.   MKLAPI
  739.   ───────────────────────────────────────────────────────────────────────────
  740.   
  741.   
  742.   OS/2 AND DOS DIFFERENCES
  743.  
  744.   The OS/2-drivers differ from the DOS drivers:
  745.  
  746.   ■  The OS/2-drivers are written in C-language, the DOS drivers in
  747.      Assembler.
  748.  
  749.   ■  The OS/2-driver makes use of the services provided by the standard OS/2
  750.      communications driver COM02.SYS (for PS/2) or COM01.SYS for others under
  751.      OS/2 version 1.3, and COM.SYS for OS/2 version 2.0.  The DOS driver
  752.      interfaces directly with the PC hardware.
  753.  
  754.   ■  The OS/2-driver makes use of the standard OS/2 facilities for
  755.      multithreading (task signalling is done with semaphores).  The DOS
  756.      driver performs a form of multi-tasking, driven by interrupts (the
  757.      COM-port hardware and the standard DOS timer tick).
  758.  
  759.   ■  The DOS-drivers explore the possibilities of the hardware timer of the
  760.      PC to obtain a accurate time values when needed.  With the DOS
  761.      timer-tick of 55 msec the average deviation would be about 28 msec.
  762.      OS/2 does not allow access to the hardware by 'normal' applications,
  763.      therefore the OS/2-drivers use standard OS/2 function calls.  Since the
  764.      OS/2 timer tick is 31.25 msec, the average deviation will be about 16
  765.      msecs.
  766.  
  767.   The sample program under DOS chokes the processor (takes all the cycles
  768.   that are available).  This is OK in a typical single-task environment, but
  769.   not very suitable for a multitasking system.  Under OS/2 a very simple
  770.   solution for this problem is to insert  for example a DosSleep(30L) at the
  771.   end of the infinite (keyboard-) loop.  There may be better solutions.
  772.  
  773.  
  774.  
  775.  
  776.  
  777.  
  778.  
  779.  
  780.  
  781.  
  782.  
  783.  
  784.  
  785.  
  786.  
  787.  
  788.  
  789.  
  790.  
  791.  
  792.  
  793.  
  794.  
  795.  
  796.  
  797.  
  798.   ───────────────────────────────────────────────────────────────────────────
  799.                                                    Functional description  10
  800.  
  801.   MKLAPI
  802.   ───────────────────────────────────────────────────────────────────────────
  803.   
  804.   
  805.   SPECIFICATIONS
  806.  
  807.   This chapter describes the use of the provided facilities.
  808.  
  809.  
  810.   AVAILABLE FUNCTIONS
  811.  
  812.   The following user callable functions are provided:
  813.  
  814.   mklopen         Start communication with the Märklin-Interface and the
  815.                   background tasks.
  816.   mklclose        Stop background tasks and shutdown the communication with
  817.                   the Märklin-Interface.
  818.   mklputc         Transmit 1 or 2 character-commands to the
  819.                   Märklin-Interface.
  820.   mklflush        Wait until all data transmitted.
  821.   mklpurge        Discard remaining data in output buffer.
  822.   mklpoll         Start or stop polling of Märklin S88 encoder boxes.
  823.   mklgetsn        Obtain the status of 1 Märklin S88 encoder (when polling
  824.                   active).
  825.   mklstop         Set Märklin-Interface in 'stop'-state and stop polling
  826.   mklgo           Set Märklin-Interface in 'go'-state and (optionally) resume
  827.                   polling.
  828.   mklmsecs        Give accurate time in milliseconds since program start
  829.                   (only in DOS-drivers).
  830.   mkltime         Give time of last timer tick in milliseconds since program
  831.                   start.
  832. | mklstats        Provide statistics (activity counters).
  833. | mklsleep        Pause for a certain time (and give up the remainder of a
  834. |                 time slice when running in a multitasking environment).
  835. | mklsound        Sound generator like BASIC sound or OS/2 DosBeep()
  836.   mkltrace        Start or stop recording data that is being sent to
  837.                   Märklin-Interface  (only in OS/2-drivers).
  838.  
  839.   The next sections contain the specifications of available functions of the
  840.   Märklin-driver, in alphabetical sequence.
  841.  
  842.   Note: The descriptions for C-language and QuickBASIC are given both, but in
  843.   the text mainly the C-language notations are used.
  844.  
  845.  
  846.   MKLCLOSE
  847.  
  848.   Name            mklclose - close communications with the Märklin-Interface.
  849.  
  850.   C-language
  851.  
  852.                     #include "mklapi.h"
  853.                     void mklclose(void);
  854.  
  855.   QuickBASIC
  856.  
  857.                     ' $INCLUDE: 'MKLAPI.INC'
  858.                     DECLARE SUB MKLCLOSE CDECL ()
  859.  
  860.  
  861.   ───────────────────────────────────────────────────────────────────────────
  862.                                                            Specifications  11
  863.  
  864.   MKLAPI
  865.   ───────────────────────────────────────────────────────────────────────────
  866.   
  867.   
  868.   Description     The close-routine disables the communications task of the
  869.                   driver.  It should be called before termination your
  870.                   program.  Transmits and receives that were in progress will
  871.                   be terinated, data might be lost.
  872.  
  873.   Return value    Nothing.
  874.  
  875.   Related functions "mklopen" on page 15
  876.  
  877.   Warning: mklclose() is not a trivial function!  It must be used when
  878.   mklopen() has been called succesfully (under DOS).  Otherwise your system
  879.   may enter a hang-up situation when for no matter what reason your
  880.   communications port gives an interrupt.  So terminate your program always
  881.   'neatly' (so intercept Ctrl-Break in your program to prevent uncontrolled
  882.   program termination)!
  883.  
  884.  
  885.  
  886.   MKLFLUSH
  887.  
  888.   Name            mklflush - flush all buffered output.
  889.  
  890.   C-language
  891.  
  892.                     #include "mklapi.h"
  893.                     int mklflush(void);
  894.  
  895.   QuickBASIC
  896.  
  897.                     ' $INCLUDE: 'MKLAPI.INC'
  898.                     DECLARE FUNCTION FLUSH% CDECL ()
  899.  
  900.   Description     Wait until all output is sent to the Märklin-Interface.  In
  901.                   other words: wait for empty transmit buffer before
  902. |                 returning to caller.
  903.  
  904. |                 When buffered data is apparently not transmitted anymore,
  905. |                 the remaining bytes in the transmit buffer will be purged
  906. |                 and the purge statistics are updated accordingly.
  907.  
  908. | Return value    Depending on success:
  909. |                 ■  0   when no more bytes to transmit (buffer empty)
  910. |                 ■  >0  number of bytes not transmitted (purged) buffer.
  911.                   ■  -1 (DOS) last byte in hardware buffer was not
  912.                      transmitted
  913.  
  914.   Related functions "mklpurge" on page 16
  915.  
  916.  
  917.  
  918.  
  919.  
  920.  
  921.  
  922.  
  923.  
  924.   ───────────────────────────────────────────────────────────────────────────
  925.                                                            Specifications  12
  926.  
  927.   MKLAPI
  928.   ───────────────────────────────────────────────────────────────────────────
  929.   
  930.   
  931.   MKLGETSN
  932.  
  933.   Name            mklgetsn - get bit-pattern of a single Märklin S88 encoder.
  934.  
  935.   C-language
  936.  
  937.                     #include "mklapi.h"
  938.                     unsigned short int mklgetsn(short int sensor);
  939.  
  940.   QuickBASIC
  941.  
  942.                     ' $INCLUDE: 'MKLAPI.INC'
  943.                     DECLARE FUNCTION MKLGETSN% CDECL (BYVAL SENSOR%)
  944.  
  945.   Description     Get a single sensor-box word (16 bits) from the sensor
  946.                   array.
  947.  
  948.                   This function does not generate any action to the
  949.                   Märklin-Interface and returns the bitsetting immediately.
  950.                   Polling will have to be started first, with mklpoll(),
  951.                   before the reading of sensors will give meaningful results.
  952.                   Reading outside the range 1..31, or higher than the value
  953.                   as specified with the latest mklpoll(maxsensor) or
  954. |                 mklgo(maxsensor), will give unpredictable results.
  955.  
  956. |                 The Märklin-Interface is always read with 'reset'.  The
  957. |                 resulting 1-bits ('on'-switches) are cumulated until a
  958. |                 mklgetsn() is called for a specific S88.  The caller
  959. |                 obtains the cumulative bit-setting, but the sensor word is
  960. |                 refreshed immediately with the results of the last read
  961. |                 command.  Depending on the type of switche used on the
  962. |                 model railroad, and the frequency in which mklgetsn() is
  963. |                 issued by the mainline, it may be necessary to issue
  964. |                 mklgetsn() twice.  See for a further explanation: "Reading
  965. |                 Märklin S88 encoders" on page 33.
  966.  
  967.   Return value    A 16-bit word containing the current switch positions.
  968.  
  969.  
  970.  
  971.   MKLGO
  972.  
  973.   Name            mklgo - send the 'go' command.
  974.  
  975.   C-language
  976.  
  977.                     #include "mklapi.h"
  978.                     int mklgo(short int maxsensor);
  979.  
  980.   QuickBASIC
  981.  
  982.                     ' $INCLUDE: 'MKLAPI.INC'
  983.                     DECLARE FUNCTION MKLGO% CDECL (BYVAL MAXSENSOR%)
  984.  
  985.   Description     Send the 'go'-command (ASCII 96) to the Märklin-Interface
  986.  
  987.   ───────────────────────────────────────────────────────────────────────────
  988.                                                            Specifications  13
  989.  
  990.   MKLAPI
  991.   ───────────────────────────────────────────────────────────────────────────
  992.   
  993.   
  994.                   immediately.
  995.  
  996.                   The value of MAXSENSOR has the same meaning and effect as
  997.                   in mklpoll (see "mklpoll" on page 16).  Polling will be
  998.                   resumed if a non-zero parameter is specified.
  999.  
  1000.                   OS/2: The go-command is sent via a DevIOCtl operation (send
  1001.                   immediate), and will be followed by a simulated XON.  If
  1002.                   there was buffered output (before the stop-state or after
  1003.                   entering stop-state under OS/2 2.0), it will be transmitted
  1004. |                 now.
  1005.  
  1006. |                 OS/2: If the 'go'-command could not be sent, for example if
  1007. |                 the Interface is not ready to accept data, a permanent low
  1008. |                 beep will be heard until the 'go'-button on Märklin Central
  1009. |                 Control is pressed.  If an other error occured, mklgo will
  1010. |                 return an error code.
  1011.  
  1012.                   DOS: The go-command is send just as regular data.  The
  1013.                   returncode is always zero.
  1014.  
  1015.   Return value    Nothing.
  1016.  
  1017.   Related functions "mklstop" on page 21, "mklpoll" on page 16
  1018.  
  1019.  
  1020.  
  1021.   MKLMSECS
  1022.  
  1023.   Name            mklmsecs - obtain time since program start in milliseconds.
  1024.  
  1025.   C-language
  1026.  
  1027.                     #include "mklapi.h"
  1028.                     unsigned long int void mklmsecs(void);
  1029.  
  1030.   QuickBASIC
  1031.  
  1032.                     ' $INCLUDE: 'MKLAPI.INC'
  1033.                     DECLARE FUNCTION MKLMSECS& CDECL ()
  1034.  
  1035.   Description     (DOS only!) Returns the exact time in milliseconds after
  1036.                   program start without waiting for the next timer tick.
  1037.                   This might be useful for more accurate timing for special
  1038.                   purposes.  Of course it takes some time to execute the
  1039.                   necessary instructions to read the timer and format the
  1040.                   information.  On faster systems mklmsecs() gives the time a
  1041.                   little more precise than on slower systems, but even on
  1042.                   relatively slow systems it is much more precise than
  1043.                   probably needed for the purpose of mode railroad control!
  1044.                   If this very high precision is not needed, then use the
  1045.                   function mkltime().
  1046.  
  1047.                   (OS/2) This function is 100% equivalent to mkltime().
  1048.  
  1049.  
  1050.   ───────────────────────────────────────────────────────────────────────────
  1051.                                                            Specifications  14
  1052.  
  1053.   MKLAPI
  1054.   ───────────────────────────────────────────────────────────────────────────
  1055.   
  1056.   
  1057.   Return value    Time in milliseconds after program start.
  1058.  
  1059.   Related functions "mkltime" on page 22
  1060.  
  1061.  
  1062.  
  1063.   MKLOPEN
  1064.  
  1065.   Name            mklopen - open communications line
  1066.  
  1067.   C-language
  1068.  
  1069.                     #include "mklapi.h"
  1070. |                   int  mklopen(short int port, short int speed);
  1071.  
  1072.   QuickBASIC
  1073.  
  1074.                    ' $INCLUDE: 'MKLAPI.INC'
  1075. |                  DECLARE FUNCTION MKLOPEN CDECL (BYVAL PORT%, BYVAL SPEED%)
  1076.  
  1077.   Description     Open and initialise communications port driver, high
  1078.                   resolution timer (DOS only), and set all statistics
  1079.                   counters to zero.  The port-parameter may have a value of 1
  1080. |                 to 4, indicating COM1: to COM4:.  With DOS the port
  1081. |                 addresses are obtained from BIOS, with OS/2 the COM[xx].SYS
  1082. |                 device driver has them.  The interrupt levels are IRQ4 for
  1083. |                 COM1 and COM3, IRQ4 for COM2 and COM4.  As you see COM3 may
  1084. |                 conflict with COM1 (and COM2 with COM4).  You cannot use
  1085. |                 conflicting interrupt levels at the same time in most
  1086. |                 computers.
  1087.  
  1088.                   Any port will always be initialised with 8-bit, no-parity,
  1089.                   2 stop-bits.  The speed parameter should specify 2400,
  1090.                   since it is the only speed supported by the
  1091.                   Märklin-Interface.  Maybe later other values?
  1092.  
  1093.                   The counterpart of mklopen() is mklclose(), which should be
  1094.                   called before finishing your (DOS-) program.
  1095.  
  1096. | Return value    Depending on success:
  1097. |                 ■  0     - port opened succesfully
  1098. |                 ■  32    - port probably occupied by another device
  1099. |                 ■  110   - port not available
  1100. |                 ■  other - see OS/2 or DOS documentation
  1101.  
  1102. |                 With OS/2 the port is opened by a separate thread.  When
  1103. |                 the port could not be opened, the whole process will be
  1104. |                 terminated.
  1105.  
  1106.   Related functions "mklclose" on page 11, "mklstats" on page 19
  1107.  
  1108.  
  1109.  
  1110.  
  1111.  
  1112.  
  1113.   ───────────────────────────────────────────────────────────────────────────
  1114.                                                            Specifications  15
  1115.  
  1116.   MKLAPI
  1117.   ───────────────────────────────────────────────────────────────────────────
  1118.   
  1119.   
  1120.   MKLPOLL
  1121.  
  1122.   Name            mklpoll - start periodic reading of Märklin S88 encoder.
  1123.  
  1124.   C-language
  1125.  
  1126.                     #include "mklapi.h"
  1127.                     void mklpoll(unsigned int maxsensor);
  1128.  
  1129.   QuickBASIC
  1130.  
  1131.                     ' $INCLUDE: 'MKLAPI.INC'
  1132.                     DECLARE SUB MKLPOLL CDECL (BYVAL MAXSENSOR%)
  1133.  
  1134.   Description     Märklin S88 encoderboxes 1..MAXSENSOR will be read by a
  1135.                   'background' process.
  1136.  
  1137.                   When starting the polling process a 'read with reset' is
  1138.                   issued.  The responses of the read-operation are stored in
  1139.                   sensor-arrays.  Each word of the array can be read
  1140.                   individually at any time with mklgetsn().  See for details
  1141.                   "Reading Märklin S88 encoders" on page 33.
  1142.  
  1143.   Return value    Nothing
  1144.  
  1145.   Related functions "mklgo" on page 13 and "mklgetsn" on page 13
  1146.  
  1147.  
  1148.  
  1149.   MKLPURGE
  1150.  
  1151.   Name            mklpurge - purge output buffer
  1152.  
  1153.   C-language
  1154.  
  1155.                     #include "mklapi.h"
  1156.                     void mklpurge(void);
  1157.  
  1158.   QuickBASIC
  1159.  
  1160.                     ' $INCLUDE: 'MKLAPI.INC'
  1161.                     DECLARE SUB MKLPURGE CDECL ()
  1162.  
  1163.   Description     Discard current contents of output buffer.  If the output
  1164.                   buffer does contain any characters, these are not sent tot
  1165.                   the Interface.  After purging the current contents, control
  1166.                   is immediately returned.  See also "mklflush" on page 12.
  1167.  
  1168.                   Note: This function is currently available in the driver
  1169.                   for DOS.
  1170.  
  1171.   Return value    Nothing.
  1172.  
  1173.   Related functions "mklflush" on page 12
  1174.  
  1175.  
  1176.   ───────────────────────────────────────────────────────────────────────────
  1177.                                                            Specifications  16
  1178.  
  1179.   MKLAPI
  1180.   ───────────────────────────────────────────────────────────────────────────
  1181.   
  1182.   
  1183.   MKLPUTC
  1184.  
  1185.   Name            mklputc - send 1 or 2 characters to the interface
  1186.  
  1187.   C-language
  1188.  
  1189.                     #include "mklapi.h"
  1190.                     int mklputc(unsigned int word);
  1191.  
  1192.   QuickBASIC
  1193.  
  1194.                     ' $INCLUDE: 'MKLAPI.INC'
  1195.                     DECLARE FUNCTION MKLPUTC% CDECL (BYVAL WORD%)
  1196.  
  1197.   Description     Send 1 or 2 characters to the Märklin-Interface.  The
  1198.                   'word' is interpreted as two contiguous characters.  The
  1199.                   low order byte of the word is sent first, followed by the
  1200.                   high-order byte.  If the high is not sent when zero.  The
  1201.                   exception to this rule is: if the first byte is a
  1202.                   switch-command (ASCII 33 or 34), then the second byte will
  1203.                   be sent, even when zero.
  1204.  
  1205.                   This function returns immediately, and does not wait for
  1206.                   the bytes to be actually transmitted to the interface.  The
  1207.                   communications task will take care to send the buffered
  1208.                   character(s) to the Märklin-Interface.
  1209.  
  1210.                   Coding example to signal speed 8 to loc 27:
  1211.  
  1212.                       rc = mklputc( 27*256 + 8)
  1213.  
  1214.                   For C-language programs it is highly recommended to use the
  1215.                   provided macro's for sending 1 or 2 character commands (see
  1216.                   "Macro Specifications" on page 23).
  1217.  
  1218.                   Warning: When there is no room in the output buffer, then
  1219.                   both  characters will be discarded.
  1220.  
  1221.   Return value     0   character(s) are accepted by the driver.
  1222.  
  1223.                   -1   characters NOT accepted: output discarded.
  1224.  
  1225.   Note: If you use mklputc() while the driver is in 'stop-state' (see
  1226.   "mklstop" on page 21):
  1227.  
  1228.   ■  the OS/2-drivers issue a short high-pitch beep.  With OS/2 2.0 the data
  1229.      might be buffered and transmitted after mklgo().  This depends on the
  1230.      used device driver for the COM-port.  COM[xx].SYS does not buffer, but
  1231.      SIO.SYS does (until its 4KB buffer is full).
  1232.   ■  the DOS-drivers do not generate a warning and will discard the data
  1233.      until the stop-state is left via a call to mklgo().
  1234.  
  1235.  
  1236.  
  1237.  
  1238.  
  1239.   ───────────────────────────────────────────────────────────────────────────
  1240.                                                            Specifications  17
  1241.  
  1242.   MKLAPI
  1243.   ───────────────────────────────────────────────────────────────────────────
  1244.   
  1245.   
  1246.   MKLSLEEP
  1247.  
  1248. | Name            mklsleep - pause some time and yield processor
  1249.  
  1250. | C-language
  1251.  
  1252. |                   #include "mklapi.h"
  1253. |                   void mklsleep(short int pause);
  1254.  
  1255. | QuickBASIC
  1256.  
  1257. |                   ' $INCLUDE: 'MKLAPI.INC'
  1258. |                   DECLARE SUB MKLSLEEP CDECL (BYVAL PAUSE%)
  1259.  
  1260. | Description     This function provides two facilities:
  1261. |                 ■  It does not return to the caller before the indicated
  1262. |                    pause-interval (im milliseconds) has expired.
  1263. |                 ■  In a multitasking environment (OS/2, DesqView, Windows)
  1264. |                    it releases the processor for this task.
  1265.  
  1266. |                 In the OS/2-driver this function is equivalent to
  1267. |                 DosSleep().  In the DOS-driver it is implemented as a loop
  1268. |                 with an imbedded test for multitasking, in the OS/2-driver
  1269. |                 as DosSleep().
  1270.  
  1271. |                 The pause should be specified in milliseconds, and thus
  1272. |                 cannot exceed about 32 seconds!  The specified
  1273. |                 pause-interval is rounded to the next timer tick, but may
  1274. |                 be even larger when the multitasker decides not to give
  1275. |                 control yet to this task after expiration of the interval!
  1276.  
  1277.                   When running a DOS-program in a multitasking environment
  1278.                   (OS/2, Desqview, Windows, etc.), it is desirable to give
  1279.                   control back to the multitasker, when the program does not
  1280.                   need the processor for some time.  This part of mklsleep()
  1281.                   is experimental, it may not work with all multitaskers.
  1282.                   The use of mklsleep is not absolutely needed with
  1283.                   pre-emptive multitaskers (like OS/2), but is strongly
  1284.                   recommended.  In all cases it reduces CPU utilisation and
  1285.                   leaves processor time for other tasks.
  1286.  
  1287.   Return value    Nothing.
  1288.  
  1289.  
  1290.  
  1291.   MKLSOUND
  1292.  
  1293.   Name            mklsound - give a 'beep'
  1294.  
  1295.   C-language
  1296.  
  1297.                     #include "mklapi.h"
  1298.                     void mklsound(short int freq, short int time)
  1299.  
  1300.   QuickBASIC
  1301.  
  1302.   ───────────────────────────────────────────────────────────────────────────
  1303.                                                            Specifications  18
  1304.  
  1305.   MKLAPI
  1306.   ───────────────────────────────────────────────────────────────────────────
  1307.   
  1308.   
  1309.                     ' $INCLUDE: 'MKLAPI.INC'
  1310.                     DECLARE SUB MKLSOUND CDECL (BYVAL FREQ%, BYVAL TIME%)
  1311.  
  1312.   Description     Produces a beep-tone with frequency 'freq' expressed in
  1313.                   Hertz, during a period 'time' expressed in milliseconds.
  1314.                   The tone is played in background, all processing continues
  1315.                   without delays or slowdown of the system.
  1316.  
  1317.                   DOS: A beep can be stopped prematurely by calling
  1318.                   mklsound() with a zero frequency, or by mklclose().  A beep
  1319.                   can be changed by mklsound() with a different frequency.
  1320. |                 This will stop any previous beep.
  1321.  
  1322. |                 OS/2: mklsound is implemented as DosBeep and thus behaves
  1323. |                 exactly like it.  It is included in the OS/2 driver only
  1324. |                 for source compatibility between OS/2 and DOS programs
  1325. |                 using MKLAPI.
  1326.  
  1327.   Return value    Nothing.
  1328.  
  1329.  
  1330.  
  1331.   MKLSTATS
  1332.  
  1333.   Name            mklstats - obtain content of statistics counter.
  1334.  
  1335.   C-language
  1336.  
  1337.                     #include "mklapi.h"
  1338.                     long int mklstats(int counter);
  1339.  
  1340.   QuickBASIC
  1341.  
  1342.                     ' $INCLUDE: 'MKLAPI.INC'
  1343.                     DECLARE FUNCTION MKLSTATS& CDECL (BYVAL COUNTER%)
  1344.  
  1345.   Description     Obtain value of an internal counter in MKLAPI for
  1346.                   statistical purposes.  All counters will be reset to zero
  1347.                   with mklopen(), and can also be reset by a user program
  1348.                   through specification of 0 (zero) as parameter.
  1349.  
  1350.                   To read a counter specify a number in the range: 1 to 6.
  1351.                   The counters (by number) have the following contents:
  1352.                   1   Number of accepted commands, including polling-commands
  1353.                       (commands to read S88's).  Since the we use a buffering
  1354.                       mechanism, not all of these commands may have been
  1355.                       transmitted actually!
  1356.                   2   Number of internally generated commands to read S88's
  1357.                       ('polls').
  1358.                   3   Number of commands that have been discarded.  Reasons
  1359.                       may be:
  1360.                       ■  system is in 'stop-state'
  1361.                       ■  transmit buffer is full
  1362.                   4   Number of bytes that were transmitted.  With the
  1363.                       DOS-driver these bytes are actually transmitted to the
  1364.  
  1365.   ───────────────────────────────────────────────────────────────────────────
  1366.                                                            Specifications  19
  1367.  
  1368.   MKLAPI
  1369.   ───────────────────────────────────────────────────────────────────────────
  1370.   
  1371.   
  1372.                       COM-port, with OS/2 they were accepted by the device
  1373.                       driver of the COM-port.
  1374.                   5   Number of received bytes (most likely as result
  1375.                       commands to read S88's).
  1376.                   6   Number of bytes that were purged (discarded after first
  1377.                       being accepted, but before actually being transmitted
  1378.                       to the Märklin-Interface).  Reasons may be:
  1379.                       ■  there were commands buffered while mklstop() was
  1380.                          called
  1381.                       ■  mklflush() could not complete (timeout)
  1382.                       ■  commands were in the transmit buffer during a call
  1383.                          to mklpurge()
  1384.  
  1385.                       Discarded commands are not counted as 'purged', since
  1386.                       they were not accepted and never put into the transmit
  1387.                       system!
  1388.  
  1389.                       Note: Purging is not supported in the OS/2-drivers, so
  1390.                       this counter should remain zero with OS/2 programs.
  1391.  
  1392.                   Counters in the range 1 to 6 can be considered as permanent
  1393.                   feature of MKLAPI.  Counters in the range 7 to 15 are
  1394.                   mainly for debugging purposes.  The description below is
  1395.                   for information purposes only, do not use them in your
  1396.                   program, as they may be incorrect, their meaning be changed
  1397.                   in a next version of MKLAPI, or may not be active at all in
  1398.                   the distributed drivers (for performance reasons).
  1399.                   7   DOS: Number of calls to mklputc while the driver's
  1400.                       transmit buffer was empty.
  1401.                   8   DOS: Number of calls to mklputc while the CTS signal is
  1402.                       'high'.
  1403.                   9   DOS: Number of calls to mklputc while the
  1404.                       hardware communications buffer was empty.
  1405.                   10  DOS: Number of calls to mklputc whereby the first or
  1406.                       only byte had to be put in the driver's communications
  1407.                       buffer.
  1408.                   11  Number of calls to mklputc with a request for 2 bytes
  1409.                       (second character always buffered).
  1410.                   12  DOS: Total number of interrupts processed by the
  1411.                       interrupthandler for the asynchronous communications
  1412.                       port.
  1413.                   13  DOS: Number of THRE interrupts.
  1414.                   14  DOS: Number of MSR interrupts (number of CTS signal
  1415.                       changes).
  1416.                   15  DOS: Situations with a pending interrupt after a
  1417.                       previous interrupt was processed.
  1418.  
  1419.                   Specification of a counter number outside the indicated
  1420.                   range will give unpredictable results.
  1421.  
  1422.   Return value    Contents of the specified counter (zero after reset).
  1423.  
  1424.   Related functions "mklopen" on page 15
  1425.  
  1426.  
  1427.  
  1428.   ───────────────────────────────────────────────────────────────────────────
  1429.                                                            Specifications  20
  1430.  
  1431.   MKLAPI
  1432.   ───────────────────────────────────────────────────────────────────────────
  1433.   
  1434.   
  1435.   MKLSTOP
  1436.  
  1437.   Name            mklstop - send the 'stop' command.
  1438.  
  1439.   C-language
  1440.  
  1441.                     #include "mklapi.h"
  1442.                     int  mklstop(void);
  1443.  
  1444.   QuickBASIC
  1445.  
  1446.                     ' $INCLUDE: 'MKLAPI.INC'
  1447.                     DECLARE FUNCTION MKLSTOP% CDECL ()
  1448.  
  1449.   Description     Send the 'stop'-command (ASCII 97) to the Märklin-Interface
  1450.                   immediately.  If polling was active at the time, it will be
  1451. |                 stopped.
  1452.  
  1453. |                 ■  OS/2:  A simulated XOFF command is used to indicate the
  1454. |                    COM-driver to hold yet buffered data.  The stop-command
  1455. |                    is then sent via a 'send-immediate' operation, ahead of
  1456. |                    data that might be in the transmit buffer.  The transmit
  1457. |                    buffer is NOT purged, held data is preserved and sent
  1458. |                    after a 'go'-command.
  1459.  
  1460. |                    You may hear a low beep while the mklstop operation is
  1461. |                    waiting to get access to the Märklin-Interface.  If an
  1462. |                    other error occured, mklstop will return an error code.
  1463.  
  1464. |                 ■  DOS: The transmit buffer is purged and the stop-command
  1465. |                    is then sent as regular data.  New output is not
  1466. |                    accepted anymore (it will be discarded).
  1467.  
  1468.                   Warning: The 'stop' command could be sent by the mainline
  1469.                   directly,  but then would bypass the administrative
  1470.                   functions of the driver.  Any train or switchpoint control
  1471.                   command received by the Märklin-Interface will cause a
  1472.                   permanent drop of the CTS signal, making the control over
  1473.                   the railroad from the computer permanently
  1474.                   unavailable.  The only possibility to resume control then
  1475.                   is by manually hitting the 'go' key on the Märklin Central
  1476.                   Control.
  1477.  
  1478.                   Note: The timer does not stop with a mklstop().  This may
  1479.                   cause strange effects from time-dependent calculations in
  1480.                   your mainline!
  1481.  
  1482.                   The 'stop' command might interfere with a 2-byte command of
  1483.                   which the first byte was already transmitted, but the
  1484.                   second byte not!  In that case the 'stop' would not be
  1485.                   recognised by the Märklin-Interface.  Two consecutive
  1486.                   'stop'-commands will prevent the acceptation by the
  1487.                   Märklin-Interface of any further commands from the
  1488.                   computer.  To make sure that the 'stop' command will be
  1489.                   processed by the Märklin-Interface, with with the least
  1490.  
  1491.   ───────────────────────────────────────────────────────────────────────────
  1492.                                                            Specifications  21
  1493.  
  1494.   MKLAPI
  1495.   ───────────────────────────────────────────────────────────────────────────
  1496.   
  1497.   
  1498.                   inconvenience, MKLAPI precedes the 'stop'-command with a
  1499.                   'go'-command:
  1500.                   ■  If there was no command in transmission, then it won't
  1501.                      harm.
  1502.                   ■  If a 'broken' 2-byte command was in progress, then the
  1503.                      'go'-byte will be interpreted by the Märklin-Interface
  1504.                      as the second byte.  This will probably have a different
  1505.                      effect than was foreseen, but since a 'stop' will
  1506.                      follow, this will be of minor importance.
  1507.  
  1508.                   A secundary effect of this setup is that it allows the
  1509.                   mainline to call mklstop() more than once.  The
  1510.                   intermediate 'go' ensures that the Märklin-Interface
  1511.                   doesn't block permanently.
  1512.  
  1513.   Return value    Error code
  1514.  
  1515.   Related functions "mklgo" on page 13
  1516.  
  1517.  
  1518.  
  1519.   MKLTIME
  1520.  
  1521.   Name            mkltime - obtain time since program start in milliseconds.
  1522.  
  1523.   C-language
  1524.  
  1525.                     #include "mklapi.h"
  1526.                     unsigned long int mkltime(void);
  1527.  
  1528.   QuickBASIC
  1529.  
  1530.                     ' $INCLUDE: 'MKLAPI.INC'
  1531.                     DECLARE FUNCTION MKLTIME& CDECL ()
  1532.  
  1533.   Description     Returns the time in milliseconds after program start since
  1534.                   it was updated with the last timer 'tick' (OS/2: 31.25
  1535.                   msecs, DOS: 55 msecs).
  1536.  
  1537.                   This is a little less accurate than mklmsecs, but consumes
  1538.                   also less processor cycles.
  1539.  
  1540.   Return value    Time in milliseconds after program start.
  1541.  
  1542.   Related functions "mklmsecs" on page 14
  1543.  
  1544.  
  1545.  
  1546.   MKLTRACE
  1547.  
  1548.   Name            mkltrace - start or stop trace
  1549.  
  1550.   C-language
  1551.  
  1552.                     #include "mklapi.h"
  1553.  
  1554.   ───────────────────────────────────────────────────────────────────────────
  1555.                                                            Specifications  22
  1556.  
  1557.   MKLAPI
  1558.   ───────────────────────────────────────────────────────────────────────────
  1559.   
  1560.   
  1561.                     void mkltrace(short int signal);
  1562.  
  1563.   QuickBASIC      trace facility not provided in DOS drivers
  1564.  
  1565.   Description     Start or stop tracing of all data that is being sent to the
  1566.                   Märklin-Interface and record the information, including a
  1567.                   timestamp into the file MKLAPI.TRC.
  1568.  
  1569.                   When signal is NOT zero, then tracing will be started, or
  1570.                   restarted (old trace data will be discarded in that case).
  1571.                   When signal is zero the trace is stopped and the trace file
  1572.                   closed.
  1573.  
  1574.                   It is my intention to replace this 'on/off' switch with a
  1575.                   trace level facility (selection of events or data to be
  1576.                   traced).
  1577.  
  1578.                   Note: Since a buffered communications interface is used,
  1579.                   the recording of trace data takes place at the moment the
  1580.                   data is sent to the buffer.  So the timestamp does not
  1581.                   reflect the exact transmission time.  Especially at moments
  1582.                   when Märklin-Interface does not accept data (for example
  1583.                   when it is transmitting Märklin S88 encoder-data), there
  1584.                   may be a significant time difference!
  1585.  
  1586.                   The utility MKLTRFMT.EXE can be used to produce a formatted
  1587.                   trace report.  All commands are printed hexadecimal and
  1588.                   interpreted.
  1589.  
  1590.                   See for details about the trace facility and a sample
  1591.                   output: "Appendix B.  Trace facility" on page 40.
  1592.  
  1593.   Return value    Nothing.
  1594.  
  1595.   Note: Tracing is not provided by the DOS-drivers, but a dummy function is
  1596.   provided for combined OS/2 and OS/2 programs.
  1597.  
  1598.  
  1599.   MACRO SPECIFICATIONS
  1600.  
  1601.   A number of C-language only macro's is provided to make specification of
  1602.   some function-calls a little more simple, and to take care of possibly
  1603.   needed data conversion.
  1604.  
  1605.  
  1606.   MKLPUT1C
  1607.  
  1608.   Name            mklput1c - send a single character to the interface.
  1609.  
  1610.   Usage           #include "mklapi.h"
  1611.  
  1612.                   void mklput1c(char);
  1613.  
  1614.   Prototype in    mklapi.h
  1615.  
  1616.  
  1617.   ───────────────────────────────────────────────────────────────────────────
  1618.                                                            Specifications  23
  1619.  
  1620.   MKLAPI
  1621.   ───────────────────────────────────────────────────────────────────────────
  1622.   
  1623.   
  1624.   Description     Macro to send a single character in the output buffer.  The
  1625.                   macro will expand into a mklputc().
  1626.  
  1627.   Return value    See "mklputc" on page 17.
  1628.  
  1629.  
  1630.  
  1631.   MKLPUT2C
  1632.  
  1633.   Name            mklput2c - send two characters to the interface.
  1634.  
  1635.   Usage           #include "mklapi.h"
  1636.  
  1637.                   void mklput2c(char1,char2);
  1638.  
  1639.   Prototype in    mklapi.h
  1640.  
  1641.   Description     Macro to send two consecutive character in the output
  1642.                   buffer.  The characters will guaranteed be sent in the
  1643.                   given order, without the risk of intervening characters by
  1644.                   the polling mechanism.  The macro will expand into a
  1645.                   mklputc().
  1646.  
  1647.   Return value    See "mklputc" on page 17.
  1648.  
  1649.  
  1650.  
  1651.   USE OF TIMER
  1652.  
  1653.   At program start with mklopen(), the system time is taken as base for the
  1654.   functions mkltime and mklmsecs.  These functions return a value in
  1655.   milliseconds after mklopen().
  1656.  
  1657.   The OS/2-driver uses standard OS/2 facilities, which will allow a precision
  1658.   of about 16 msecs (the time is updated in OS/2 control blocks every 31.25
  1659.   msecs).
  1660.  
  1661.   The DOS-driver uses the system hardware to obtain the system time.  This
  1662.   allows a precision of 1 msec (with the function mklmsecs()).  The function
  1663.   mkltime() gives a precision of about 28 msecs, and takes less machine
  1664.   instructions, which might be sufficient for most purposes.
  1665.  
  1666.   The use of this timer facility provided by the MKLAPI-drivers has the
  1667.   following advantages:
  1668.  
  1669.   ■  It is independent of system (processor) speed and other tasks running in
  1670.      your system.  Many sample programs use some kind of processing loop to
  1671.      obtain a 'wait'-period, which might be dependent on processor speed and
  1672.      'choke' the processor, during which time no other useful work is
  1673.      possible, or at least it is pretty complicated.
  1674.  
  1675.   ■  It is available with very little processor cycles, so it is not needed
  1676.      to call a 'universal' compiler-provided timer routine, which are
  1677.      generally much more cycle consuming.
  1678.  
  1679.  
  1680.   ───────────────────────────────────────────────────────────────────────────
  1681.                                                            Specifications  24
  1682.  
  1683.   MKLAPI
  1684.   ───────────────────────────────────────────────────────────────────────────
  1685.   
  1686.   
  1687.   The timer can be used for example for:
  1688.  
  1689.   ■  The application of an event-queue (for timed operations).
  1690.   ■  'Wait'-intervals during without programming a loop.
  1691.   ■  Simulation of train mass (inertia) through gradually increasing or
  1692.      decreasing loc-speed.
  1693.  
  1694.   If you register this package, you'll receive a sample program which makes
  1695.   use of this feature.
  1696.  
  1697.   It is recommended to use mklsleep() in cyclic operations when running in a
  1698.   multitasking environment sucha as Windows, DesqView or in a DOS-session
  1699.   under OS/2.
  1700.  
  1701.  
  1702.   QUICKBASIC FUNCTION SPECIFICATIONS
  1703.  
  1704.   The functionality of the Märklin-driver for QuickBASIC is the same as for
  1705.   the drivers for C-language.  However the following should be noted:
  1706.  
  1707.   ■  BASIC does not allow the underscore-sign ("_") in names, as is very
  1708.      common in C-language.  Therefore the FUNCTIONS and DATA fields in the
  1709.      Märklin-driver for QuickBASIC have been adapted a little to BASIC
  1710.      conventions since in 0.9 of these drivers.  All other differences are
  1711.      'under the cover' (but see next item).
  1712.  
  1713.   ■  C-language uses by default a different way of parameter passing than
  1714.      BASIC, PASCAL and some other languages.  But MicroSoft QuickBASIC
  1715.      compiler 4.5 allows the C-language convention to be used, and the
  1716.      Märklin-driver for QuickBASIC expects this convention to be used.  This
  1717.      is reflected in the function specifications in MKLAPI.INC.  If you use
  1718.      the MKLAPI.INC file (strongly recommended!), then you won't have to
  1719.      worry about these conventions.
  1720.  
  1721.  
  1722.  
  1723.   ERRORS AND SIGNALS
  1724.  
  1725.   The driver is designed not to disturb your screen with error-messages.
  1726. | Therefore audiable signals are used to indicate unexpected problems.
  1727.  
  1728. | The OS/2 and DOS-drivers produce the same warning-signals:
  1729.  
  1730. | very high pitch, short 3000 Hz, 20 msec: Märklin-Interface  The driver is
  1731. |             in stop-state, but some routine tries to send commands, which
  1732. |             are discarded.
  1733.  
  1734. | medium high pitch, long 2000 Hz, 300 msec: Märklin-Interface seems to be
  1735. |             long-term blocked.  The transmit task could not deliver its
  1736. |             data.  Most likely the transmit buffer is full.  Check the
  1737. |             'stop'-light on the Märklin Central Control if a stop-condition
  1738. |             is the cause (manually set, or electrical problem).
  1739.  
  1740. | high pitch, short 1000 Hz, 20 msec: A command-transmission did not finish
  1741. |             within the normal time.  Too many commands may be queued, maybe
  1742.  
  1743.   ───────────────────────────────────────────────────────────────────────────
  1744.                                                            Specifications  25
  1745.  
  1746.   MKLAPI
  1747.   ───────────────────────────────────────────────────────────────────────────
  1748.   
  1749.   
  1750. |             because of a program loop.
  1751.  
  1752. | medium pitch, short 440 Hz, 100 msec: Flushing of the buffer could not take
  1753. |             place in the expected time.  Either transmission of buffered
  1754. |             data doesn't take place, or the buffer is being filled during
  1755. |             flushing faster than can be transmitted.
  1756.  
  1757. | low pitch, short 200 Hz, 100 msec: a communications error occurred (OS/2).
  1758. |             Debugging information might be sent to STDERR (which you might
  1759. |             have redirected to a log-file to prevent disturbance of your
  1760. |             screen).
  1761.  
  1762.  
  1763.  
  1764.  
  1765.  
  1766.  
  1767.  
  1768.  
  1769.  
  1770.  
  1771.  
  1772.  
  1773.  
  1774.  
  1775.  
  1776.  
  1777.  
  1778.  
  1779.  
  1780.  
  1781.  
  1782.  
  1783.  
  1784.  
  1785.  
  1786.  
  1787.  
  1788.  
  1789.  
  1790.  
  1791.  
  1792.  
  1793.  
  1794.  
  1795.  
  1796.  
  1797.  
  1798.  
  1799.  
  1800.  
  1801.  
  1802.  
  1803.  
  1804.  
  1805.  
  1806.   ───────────────────────────────────────────────────────────────────────────
  1807.                                                            Specifications  26
  1808.  
  1809.   MKLAPI
  1810.   ───────────────────────────────────────────────────────────────────────────
  1811.   
  1812.   
  1813.   INSTALLATION
  1814.  
  1815.  
  1816.  
  1817.   APPLICATION DEVELOPMENT CONSIDERATIONS
  1818.  
  1819.   This MKLAPI is a program development tool with a C-language or QuickBASIC
  1820.   compiler.  You need MKLAPI.H (MKLAPI.INC for BASIC) at compile-time and one
  1821.   of the .OBJ files at LINK-time.  It is an addition to the compiler and
  1822.   possibly other toolkits you may have for other purposes.
  1823.  
  1824.  
  1825.   C-COMPILER CONSIDERATIONS
  1826.  
  1827.   The following compiler properties apply.
  1828.  
  1829.   ■  The file MKLAPI.H must be #included in the program that references the
  1830.      driver routines (you can use the same header-file for OS/2 and DOS).
  1831.  
  1832.   ■  Memory model: OS/2: LARGE; DOS: SMALL or LARGE (your choice)
  1833.  
  1834.   ■  Calling conventions: C
  1835.  
  1836.   ■  OS/2:  The '/MT' parameter should be specified with MicroSoft C-compiler
  1837.      6.00a  With IBM C SET/2 compiler '/Gm' should be specified among other
  1838.      parameters.
  1839.  
  1840.   ■  Generate underbars: On (Turbo-C option).
  1841.  
  1842.   Other compiler options are (probably) not of influence on the use of the
  1843.   Märklin-driver.
  1844.  
  1845.  
  1846.   MICROSOFT QUICKBASIC COMPILER 4.5 CONSIDERATIONS
  1847.  
  1848.   The QuickBASIC compiler is needed to create an object deck of your BASIC
  1849.   program.  This OBJect file is combined with LMKLAPI.OBJ file as provided by
  1850.   this MKLAPI package to build an EXE-file with the LINK utility.
  1851.  
  1852.   ■  Calling conventions: C (DECLARE SUB|FUNCTION xxx CDECL ... etc)
  1853.  
  1854.  
  1855.  
  1856.   BUILDING AN EXE-FILE
  1857.  
  1858.   One of the OBJect files should be included in the link-step with your own
  1859.   OBJect file(s).  I prefer to Compile and LINK with the help of the (N)MAKE
  1860.   utility.
  1861.  
  1862.  
  1863.  
  1864.  
  1865.  
  1866.  
  1867.  
  1868.  
  1869.   ───────────────────────────────────────────────────────────────────────────
  1870.                                                              Installation  27
  1871.  
  1872.   MKLAPI
  1873.   ───────────────────────────────────────────────────────────────────────────
  1874.   
  1875.   
  1876.   C-LANGUAGE AND DOS
  1877.  
  1878.   For the DOS sample application ("TRAIN") I use the following MAKE-file:
  1879.  
  1880.   ┌─────────────────────────────────────────────────────────────────────────┐
  1881.   │                                                                         │
  1882.   │ #                                                                       │
  1883.   │ # MAKE TRAIN: Marklin Digital Train Control program (DOS version)       │
  1884.   │ #             - both SMARKLIN.OBJ and LMARKLIN.OBJ generated            │
  1885.   │ #             - LARGE memory model version used for TRAIN.EXE           │
  1886.   │ #             - With the compiler variable __DOS__ specified, certain   │
  1887.   │ #               #include-file selections are made in train2.c. When     │
  1888.   │ #               __DOS__ not specified the OS/2-inlcudes are selected.   │
  1889.   │ #                                                                       │
  1890.   │                                                                         │
  1891.   │ MDL=L                                                                   │
  1892.   │ CL=-c -Zl -Zp -G0 -W3 -A$(MDL) -D__DOS__ -Fotrain.obj -Ot               │
  1893.   │ LK=/NOD /PACKC:65500 /ST:4000                                           │
  1894.   │                                                                         │
  1895.   │ train.exe: train.obj smklapi.obj lmklapi.obj                            │
  1896.   │   LINK  train+$(MDL)mklapi, train $(LK), nul, $(MDL)LIBCER;             │
  1897.   │                                                                         │
  1898.   │ train.obj: train2.c train.h train.mak attrib.h attrib2.h common.h\      │
  1899.   │            matrix.h mklapi.h                                            │
  1900.   │   CL $(CL) train2.c                                                     │
  1901.   │                                                                         │
  1902.   │ smklapi.obj: mklapi.asm mklapi.h train.mak                              │
  1903.   │   MASM -Dsmall mklapi.asm,smklapi;                                      │
  1904.   │                                                                         │
  1905.   │ lmklapi.obj: mklapi.asm mklapi.h train.mak                              │
  1906.   │   MASM -Dlarge mklapi.asm,lmklapi;                                      │
  1907.   │                                                                         │
  1908.   │                                                                         │
  1909.   └─────────────────────────────────────────────────────────────────────────┘
  1910.  
  1911.   Note: It contains switches to control the use of large or small memory
  1912.   models.
  1913.  
  1914.  
  1915.   C-LANGUAGE AND BASIC
  1916.  
  1917.   For a simple test-program in QuickBASIC I use the following batch-file:
  1918.  
  1919.   ┌─────────────────────────────────────────────────────────────────────────┐
  1920.   │                                                                         │
  1921.   │ @echo off                                                               │
  1922.   │ rem                                                                     │
  1923.   │ rem Build Marklin Digital Test program for DOS QuickBASIC               │
  1924.   │ rem Note: LMKLAPI.OBJ fetched from \C2\MARKLIN subdirectory             │
  1925.   │ rem                                                                     │
  1926.   │ BC    test /S;                                                          │
  1927.   │ if errorlevel 0  LINK  test+\c2\marklin\lmklapi;                        │
  1928.   │                                                                         │
  1929.   └─────────────────────────────────────────────────────────────────────────┘
  1930.  
  1931.  
  1932.   ───────────────────────────────────────────────────────────────────────────
  1933.                                                              Installation  28
  1934.  
  1935.   MKLAPI
  1936.   ───────────────────────────────────────────────────────────────────────────
  1937.   
  1938.   
  1939.   Note: With MicroSoft QuickBASIC compiler 4.5 the LMKLAPI.OBJ need to be
  1940.   included in the link.  models.
  1941.  
  1942.  
  1943.   C-LANGUAGE AND OS2 1.3
  1944.  
  1945.   For the 16-bits OS/2-sample application ("TRAIN2") I use the following
  1946.   MAKE-file for MicroSoft C-compiler 6.00a and IBM OS/2 Program Development
  1947.   Toolkit 1.2/1.3:
  1948.  
  1949.   ┌─────────────────────────────────────────────────────────────────────────┐
  1950.   │                                                                         │
  1951.   │ #                                                                       │
  1952.   │ # MAKE TREIN: Marklin Digital Train Control                             │
  1953.   │ #                                                                       │
  1954.   │ # To be used with MicroSoft C-compiler 6.00a                            │
  1955.   │ #                                                                       │
  1956.   │ # With IBM C/2 1.1 compiler specify '__IBMC2__' compiler option         │
  1957.   │ #                                                                       │
  1958.   │ # 'OS2' compiler variable needed for OS/2 object of TRAIN2!             │
  1959.   │ #                                                                       │
  1960.   │                                                                         │
  1961.   │ CL=-c -Zp -Zl -W3 -MT                                                   │
  1962.   │ LK=/A:16 /PACKC:65000 /NOI /NOD                                         │
  1963.   │ L1=LLIBCMT OS2                                                          │
  1964.   │                                                                         │
  1965.   │ train2.exe: train2.obj mklapi2.obj train2.def                           │
  1966.   │    LINK train2+mklapi2, $@ $(LK), NUL, $(L1), train2.def                │
  1967.   │                                                                         │
  1968.   │ train2.obj: train2.c train2.h attrib2.h mklapi.h common.h matrix.h      │
  1969.   │    CL $(CL) train2.c                                                    │
  1970.   │                                                                         │
  1971.   │ mklapi2.obj: mklapi2.c                                                  │
  1972.   │    CL $(CL) mklapi2.c                                                   │
  1973.   │                                                                         │
  1974.   │                                                                         │
  1975.   └─────────────────────────────────────────────────────────────────────────┘
  1976.  
  1977.   The contents of the corresponding LINK .DEF-file are:
  1978.  
  1979.   ┌─────────────────────────────────────────────────────────────────────────┐
  1980.   │                                                                         │
  1981.   │ ;                                                                       │
  1982.   │ ;******* Marklin Train Control Program  Definition File (.DEF) ******** │
  1983.   │ ;        For: 1)  16-bit version for OS/2 1.3 and MS C-compiler         │
  1984.   │ ;             2)  32-bit version for OS/2 2.0 and IBM C Set/2 compiler  │
  1985.   │                                                                         │
  1986.   │ NAME    TRAIN2  WINDOWCOMPAT                                            │
  1987.   │                                                                         │
  1988.   │ DESCRIPTION 'Marklin Train Control. Copyright (1991,93) Rob Hamerling'  │
  1989.   │ PROTMODE                                                                │
  1990.   │ HEAPSIZE   4096                                                         │
  1991.   │ STACKSIZE  8192                                                         │
  1992.   │                                                                         │
  1993.   └─────────────────────────────────────────────────────────────────────────┘
  1994.  
  1995.   ───────────────────────────────────────────────────────────────────────────
  1996.                                                              Installation  29
  1997.  
  1998.   MKLAPI
  1999.   ───────────────────────────────────────────────────────────────────────────
  2000.   
  2001.   
  2002.   C-LANGUAGE AND OS2 2.0+
  2003.  
  2004.   For the 32-bits OS/2-sample application ("TRAIN3"), the following MAKE-file
  2005.   is appropriate for IBM C SET/2 compiler and IBM OS/2 Program Development
  2006.   Toolkit 2.0:
  2007.  
  2008.   ┌─────────────────────────────────────────────────────────────────────────┐
  2009.   │                                                                         │
  2010.   │ #                                                                       │
  2011.   │ # MAKE TREIN: Marklin Digital Train Control program                     │
  2012.   │ #                                                                       │
  2013.   │                                                                         │
  2014.   │ CL=/c /G3 /Gd+ /Gm+ /Re /Se /Sm /Ss                                     │
  2015.   │ LK=/NOI /PACKC:65500 /ALIGN:4 /BASE:0x10000 /EXEPACK                    │
  2016.   │                                                                         │
  2017.   │ train3.exe: train3.obj mklapi3.obj                                      │
  2018.   │    link386 $**, $@ $(LK), NUL, , train2.def                             │
  2019.   │                                                                         │
  2020.   │ train3.obj: train2.c                                                    │
  2021.   │    icc $(CL) /Fotrain3.obj train2.c                                     │
  2022.   │                                                                         │
  2023.   │ mklapi3.obj: mklapi2.c mklapi.h                                         │
  2024.   │    icc $(CL) /Fomklapi3.obj mklapi2.c                                   │
  2025.   │                                                                         │
  2026.   │                                                                         │
  2027.   └─────────────────────────────────────────────────────────────────────────┘
  2028.  
  2029.   Note: The same .DEF-file is used as for the 16-bit version.
  2030.  
  2031.  
  2032.   STORAGE AND PERFORMANCE
  2033.  
  2034.   There is yet not much to say about storage and performance of the driver.
  2035.   It is highly optimised code, and probably only a minor part of the 'real'
  2036.   railroad control program.
  2037.  
  2038.  
  2039.   MEMORY UTILISATION
  2040.  
  2041.   It is difficult to say how many storage is occupied by the OS/2-version of
  2042.   the Märklin-driver.
  2043.  
  2044.   The DOS-version requires about 4K bytes of storage.
  2045.  
  2046.  
  2047.   PROCESSOR UTILISATION
  2048.  
  2049.   You might be curious about the cycles that will be consumed by the polling
  2050.   task.  I've done some measurements under OS/2 version 1.3 with the sample
  2051.   program TRAIN2.  On an 8 Mhz AT (80286) the polling takes between 10% and
  2052.   12% of the processor time (difference in processor utilisation between
  2053.   polling ON and OFF).  This number is practically independent of the number
  2054.   of Märklin S88 encoder's that are specified for polling, but the polling
  2055.   frequency is also lower!
  2056.  
  2057.  
  2058.   ───────────────────────────────────────────────────────────────────────────
  2059.                                                              Installation  30
  2060.  
  2061.   MKLAPI
  2062.   ───────────────────────────────────────────────────────────────────────────
  2063.   
  2064.   
  2065.   COMMENTS, REMARKS, BUG-REPORTS
  2066.  
  2067.   If there are bugs, requirements or questions about this Märklin-driver, the
  2068.   documentation or the sample program (that you get when you register),
  2069.   please send me a message through the FIDO network.  You can find my name
  2070.   and node-(point)-number in the introduction of this document.
  2071.  
  2072.   Enjoy and good luck with your program development!  May this driver lead to
  2073.   a very attractive and succesful model railroad control program!
  2074.  
  2075.   Do not 'forget' to register!
  2076.  
  2077.  
  2078.  
  2079.  
  2080.  
  2081.  
  2082.  
  2083.  
  2084.  
  2085.  
  2086.  
  2087.  
  2088.  
  2089.  
  2090.  
  2091.  
  2092.  
  2093.  
  2094.  
  2095.  
  2096.  
  2097.  
  2098.  
  2099.  
  2100.  
  2101.  
  2102.  
  2103.  
  2104.  
  2105.  
  2106.  
  2107.  
  2108.  
  2109.  
  2110.  
  2111.  
  2112.  
  2113.  
  2114.  
  2115.  
  2116.  
  2117.  
  2118.  
  2119.  
  2120.  
  2121.   ───────────────────────────────────────────────────────────────────────────
  2122.                                                              Installation  31
  2123.  
  2124.   MKLAPI
  2125.   ───────────────────────────────────────────────────────────────────────────
  2126.   
  2127.   
  2128.   APPENDIX A.  MKLAPI INTERNALS
  2129.  
  2130.   This appendix describes a number of design arguments for this driver and
  2131.   explains decisions where a choice had to be made.
  2132.  
  2133.  
  2134.   MULTITASKING
  2135.  
  2136.   There are many situations in real-time programming, where you want the
  2137.   system to do something for you, while in the meantime you would like to do
  2138.   something else in the mainline (before the first piece of program
  2139.   completes).
  2140.  
  2141.   An example of this is reading sensor boxes.  While you have to wait for the
  2142.   response of the Märklin S88 encoder, you might want to update your screen,
  2143.   read data from disk, or process keyboard input.  In many sample programs
  2144.   that I have seen, the wait is frequently done in the form of a short loop
  2145.   (a for- or while-statement).  This means that the processor is working, in
  2146.   fact consuming cycles, while you cannot do anything (unless you make a more
  2147.   'complicated' loop).  And in many cases you have to experiment with this
  2148.   loop to get the needed wait-interval (not too long and not too short).
  2149.   Running the same program on a machine with a different processor-speed,
  2150.   requires a change in the loop.
  2151.  
  2152.   A solution for this is to have multiple programs to run simultaneously.
  2153.   Executing multiple programs (tasks) in parallel is called multi-tasking.
  2154.   Since we are generally dealing with a single micro processor, the tasks are
  2155.   simultaneaously present in memory, but only 1 of them is actually
  2156.   processing.  There must be some mechanism to switch the processor between
  2157.   the tasks.
  2158.  
  2159.   Some operating environments have standard facilities for this (OS/2,
  2160.   Windows), but DOS doesn't.  Under DOS you have to do it yourself.  By
  2161.   intercepting hardware interupts, or the timer-tick interrupt it is possible
  2162.   to implement a kind of task-switching.
  2163.  
  2164.   The polling mechanism in the Märklin-driver is a form of multi-tasking.
  2165.   For OS/2 it uses the standard OS/2 facilities (called multi-threading), for
  2166.   DOS it uses the system timer to execute periodical actions independently
  2167.   from the main-program, and also the hardware interrupts of the asynchronous
  2168.   communications port to perform some communications work.  So in fact there
  2169.   are two 'extra' tasks in the polling mechanism:
  2170.  
  2171.   ■  Periodically send read-commands to the Märklin-Interface.
  2172.   ■  Receive the responses and put them in the appropriate place in the
  2173.      sensor-array.
  2174.  
  2175.   Although you don't have to bother about the polling mechanism, it does have
  2176.   some influence on the design of your railroad control program.  These
  2177.   practical aspects are explained below.
  2178.  
  2179.  
  2180.  
  2181.  
  2182.  
  2183.  
  2184.   ───────────────────────────────────────────────────────────────────────────
  2185.                                             Appendix A.  MKLAPI Internals  32
  2186.  
  2187.   MKLAPI
  2188.   ───────────────────────────────────────────────────────────────────────────
  2189.   
  2190.   
  2191.   READING MäRKLIN S88 ENCODERS
  2192.  
  2193.   The driver generates read-sensor commands in the following way:
  2194.  
  2195.   1. After polling is activated periodically a sensor-read command is
  2196.      transmitted to read multiple Märklin S88 encoders.
  2197.  
  2198.   2. The receive-part of the communications task is signalled that a response
  2199.      from the Märklin-Interface should be expected.  The receive continues as
  2200.      long as not all expected input is received, or an unexpected long time
  2201.      had to be waited.
  2202.  
  2203.   3. After processing the response, the system waits some time before issuing
  2204.      a new read command (typically 100 msec).
  2205.  
  2206.   4. Even if for some reason the previous poll did not finish within
  2207.      reasonable time (typically 500 msec), a new read-command is issued.
  2208.  
  2209.   5. If the transmit routine is in use by the mainline program (such as
  2210.      sending train-commands), polling is suspended for a short while (shorter
  2211.      than the normal polling interval).
  2212.  
  2213.   The Märklin-Interface documentation indicates that the average time to read
  2214.   the last poll-response is between 45 and 300 milliseconds, depending on how
  2215.   many Märklin S88 encoder's are being read.  From 'life'-tests I have
  2216.   concluded:
  2217.  
  2218.   ■  The total polling cycle (the time between two consecutive read commands)
  2219.      is so short that the delay between the change of a switch and making the
  2220.      change represented in the sensor-array is short enough for most
  2221.      practical situation.
  2222.   ■  The poll wait interval is long enough to allow sending of many commands
  2223.      from the mainline between read commands.  To make this sure there is a
  2224.      built-in priority mechanism in the polling routine: it waits with
  2225.      generating a poll when another program uses mklputc() routine!
  2226.   ■  The frequency of the polls is low enough to ensure that not all CPU
  2227.      cycles are spent on polling, in stead of 'real' work.
  2228.  
  2229.   Polling is programmed as follows:
  2230.  
  2231.   1. After calling mklpoll() of mklgo() with a non-zero parametervalue a
  2232.      '192'-byte is transmitted, meaning that the Interface will RESET the
  2233.      bits with next read-sensor commands.
  2234.   2. Periodically a '128 + MAXSENSOR' byte, meaning that the Interface will
  2235.      report a group of sensors, up till the limit that was specified with the
  2236.      latest mklpoll() or mklgo().
  2237.  
  2238.  
  2239. | The received data is collected in 2 sensor-arrays:
  2240.  
  2241. | 1. Collection of 'raw' data from the Märklin-Interface.  Array-1 always
  2242. |    represents the current switch positions of all polled S88's, apart from
  2243. |    a slight delay between consecutive reads.
  2244.  
  2245.  
  2246.  
  2247.   ───────────────────────────────────────────────────────────────────────────
  2248.                                             Appendix A.  MKLAPI Internals  33
  2249.  
  2250.   MKLAPI
  2251.   ───────────────────────────────────────────────────────────────────────────
  2252.   
  2253.   
  2254.  
  2255. |                    ╔═══════════════════╗
  2256. |                    ║                   ║
  2257. |                    ║ Marklin Interface ║
  2258. |                    ║                   ║
  2259. |                    ╚═════════════════╝
  2260. |                            ║  ║
  2261. |                            ║  ║
  2262. |     ╔══════════════════════║══║═════════════════════════════════════╗
  2263. |     ║    READ S88 1...6 ═══╝  ║                         Computer    ║
  2264. |     ║  (by polling task)      ║                                     ║
  2265. |     ║                         ║                                     ║
  2266. |     ║                         ║                                     ║
  2267. |     ║          ╔═════╦═════╦══╩══╦═════╦═════╗                      ║
  2268. |     ║  'move'  ║     ║     ║     ║     ║     ║                      ║
  2269. |     ║          ║     ║     ║     ║     ║     ║                      ║
  2270. |     ║       ╔════╦════╦════╦════╦════╦════╦══ ═               ║
  2271. |     ║       ║  1  ║  2  ║  3  ║  4  ║  5  ║  6  ║        array-1    ║
  2272. |     ║       ╚══╦══╩══╦══╩══╦╦═╩══╦══╩══╦══╩══╦══╩══ ═               ║
  2273. |     ║                       ║                                       ║
  2274. |     ║   'or'   ║     ║     ║║(2) ║     ║     ║                      ║
  2275. |     ║                       ║                                       ║
  2276. |     ║       ╔════╦════╦═══╦════╦════╦════╦══ ═               ║
  2277. |     ║       ║  1  ║  2  ║  3  ║  4  ║  5  ║  6  ║        array-2    ║
  2278. |     ║       ╚═════╩═════╩══╦══╩═════╩═════╩═════╩══ ═               ║
  2279. |     ║                      ║                                        ║
  2280. |     ║                      ║(1)   actions by: mklgetsn(3)           ║
  2281. |     ║                      ║     1. return word 3 of array-2        ║
  2282. |     ║                           2. copy word 3 array-1 to array-2  ║
  2283. |     ║                                                               ║
  2284. |     ╚═══════════════════════════════════════════════════════════════╝
  2285.  
  2286.  
  2287. | Figure 1. Organisation of reading S88's (polling): In this sample a
  2288. |           group-read of 6 S88-boxes is used.
  2289.  
  2290. | 2. Cumulative 'on'-bits since most recent mklgetsn() for each specific S88
  2291. |    in Array-2.
  2292.  
  2293. | The incoming data of the 'read group' is stored in array-1, and all 1-bits
  2294. | are copied immediately to array 2 with an 'or'-operation.  So array-2 is a
  2295. | cumulation of 'on' switch positions during a certain period.
  2296.  
  2297. | When mklgetsn(x) is executed, the contents of word-x in array-2 are
  2298. | returned to the caller.  At the same time word-x in array-2 is refreshed
  2299. | with the then current contents of array-1.  So a second mklgetsn()
  2300. | immediately after the first gives the actual status ((3)).
  2301. | A second call is required if you want to know for sure if the switch is
  2302. | currently in the 'off'-position after it has been 'on' since the most
  2303. | recent mklgetsn().
  2304.  
  2305.   
  2306.   ────────────────────
  2307.   (3)     Function mklgetsn might be changed later to be able to specify that
  2308.           you need data from the first or from the second array.
  2309.  
  2310.   ───────────────────────────────────────────────────────────────────────────
  2311.                                             Appendix A.  MKLAPI Internals  34
  2312.  
  2313.   MKLAPI
  2314.   ───────────────────────────────────────────────────────────────────────────
  2315.   
  2316.   
  2317. | This mechanism is suitable for all types of switches that are applied in
  2318. | model-railroads, and ensures that you won't miss any 'switch-on' condition,
  2319. | even if it is 'on' during a very short period.  This organisation is
  2320. | illustrated in Reading Märklin S88 encoders  on page 33.
  2321.  
  2322.   You have to be careful with specifying more Märklin S88 encoder boxes in
  2323.   mklpoll() or mklgo() than you really have in your model railroad yard.
  2324.  
  2325.   ■  It is not useful, since the Märklin-Interface will return all zeroes for
  2326.      not-connected Märklin S88 encoder's.
  2327.   ■  During the time the Märklin-Interface sends the responses to the
  2328.      computer, no commands are accepted by the Interface.
  2329.  
  2330.   So specifying more Märklin S88 encoders than really active will unnecessary
  2331.   downgrade the responsiveness of your program.  You might decide to stop
  2332. | polling during processor-intensive work, or not to use polling at all.
  2333.  
  2334. | Note: The following consequences of this mechanism:
  2335.  
  2336. | ■  If you use this driver, you should not issue read-commands from the
  2337. |    mainline.  The driver does not intercept read-commands from the
  2338. |    mainline, but it will intercept all data from the Interface and not
  2339. |    return it to the mainline!  This will disturb the administration of the
  2340. |    internal sensor numbering, which is depending entirely on the number of
  2341. |    incoming bytes.
  2342. | ■  This driver does not yet support physically reading of individual
  2343. |    Märklin S88 encoders, and it is not possible to use polling with
  2344. |    no-reset (command 128 in stead of 192).  This may look like a
  2345. |    limitation, especially with the use of reed-switches or contact-rails.
  2346. |    But once you are familiar with the convenience of the polling mechanism
  2347. |    and the functionality of mklgetsn(), this should not be a practical
  2348. |    limitation.
  2349.  
  2350.  
  2351.  
  2352.   COMMUNICATIONS INTERFACE SPECIFICATION
  2353.  
  2354.   The Märklin-Interface contains a device driver level communication facility
  2355.   with between computer and Märklin-Interface, but with a rather high level
  2356.   interface for the application programmer.  It contains many basic
  2357.   functions, that otherwise have to be programmed yourself.  However, it
  2358.   enforces a specific organisation of your program and has some limitations.
  2359.  
  2360.   Some of the internals of the communications task are briefly explained to
  2361.   show why it works as it works now, and may prevent questions.  On the other
  2362.   hand, it may trigger suggestions for changes!  Feel free to go in
  2363.   discussion with me!
  2364.  
  2365.   Wiring          Only the Read (RD), write (TD) and Clear-to-Send (CTS) lead
  2366.                   are connected.  Thus using DTR and RTS from the computer
  2367.                   will have no effect of any kind and obviously DSR and DCD
  2368.                   (sometimes also called CD or RLSD) will not be used by the
  2369.                   Märklin-Interface  Nevertheless DTR and RTS are set by the
  2370.                   driver with mklopen().  This allows for the use of a
  2371.                   break-out box and/or another computer in stead of the
  2372.  
  2373.   ───────────────────────────────────────────────────────────────────────────
  2374.                                             Appendix A.  MKLAPI Internals  35
  2375.  
  2376.   MKLAPI
  2377.   ───────────────────────────────────────────────────────────────────────────
  2378.   
  2379.   
  2380.                   Märklin-Interface for debugging of your program (since a PC
  2381.                   commmunications program usually needs these leads to be
  2382.                   active).  The driver itself works properly without the DSR
  2383.                   and DCD leads.
  2384.  
  2385.   Speed           The Märklin-Interface allows only 2400 bps, and 8-bits
  2386.                   data, NO parity, and 2 stop bits.  These are the built-in
  2387.                   defaults of the driver, however a different speed can be
  2388.                   specified at open-time (might be useful for test and
  2389.                   debugging).
  2390.  
  2391.   FIFO            So called FIFO hardware buffering, provided by the newer
  2392.                   UART-chips (such as 16550 AFN) on asynchronous
  2393.                   communication ports is handled as follows by the drivers:
  2394.                   ■  The DOS-driver does not actively support FIFO-mode, but
  2395.                      FIFO-support is in plan.
  2396.                   ■  The OS/2-MKLAPI uses the facilities of the device driver
  2397.                      COM[xx].SYS for operation of the COM-port.  When FIFO is
  2398.                      is active for the COM-port before opening, it is left
  2399.                      active and uses this feature.  Use the MODE-command to
  2400.                      control this feature.
  2401.  
  2402.                   FIFO-mode may not provide a considerable improvement:
  2403.                   ■  The Märklin-Interface operates strictly half-duplex, it
  2404.                      is either in receive mode, or in transmit mode.  During
  2405.                      data transfer (either way) CTS is dropped while
  2406.                      transmitting each command-byte and may remain low for a
  2407.                      'considerable' time while command interpretation is in
  2408.                      progress and S88-positions are being sent back to the
  2409.                      computer.  This does not suit very well with the FIFO
  2410.                      for transmitbuffering.  It might be useful for receive,
  2411.                      since in many cases at least 2 bytes are received per
  2412.                      S88. being read.  The support for this is in
  2413.                      consideration.
  2414.                   ■  Since the speed is 2400 bps, most systems can easily
  2415.                      keep up with the non-buffered mode of operation.  The
  2416.                      highly effective interrupt handler of the DOS-driver may
  2417.                      make the netto effect of reduced CPU-cycles for
  2418.                      interrupt handling only minimal.
  2419.  
  2420.                   But FIFO-mode may be helpful in a multitasking environment.
  2421.                   Use the MODE command with BUFFER=ON, to activate it, when
  2422.                   desired.
  2423.  
  2424.   Output flow control The CTS signal is dropped by Märklin-Interface during
  2425.                   data transfer (during receive and transmit: the
  2426.                   Märklin-Interface is strictly half-duplex).  The CTS signal
  2427.                   is used for 'hardware output flow control' from the
  2428.                   computer.  So the transmit routines will not send data when
  2429.                   CTS is not high, but will automatically resume transmission
  2430.                   when CTS rises and the buffer contains any data to
  2431.                   transmit.
  2432.  
  2433.                   DOS Although not strictly needed, the DOS-version of the
  2434.                   Märklin-driver has the transmit interrupt (THRE) active to
  2435.  
  2436.   ───────────────────────────────────────────────────────────────────────────
  2437.                                             Appendix A.  MKLAPI Internals  36
  2438.  
  2439.   MKLAPI
  2440.   ───────────────────────────────────────────────────────────────────────────
  2441.   
  2442.   
  2443.                   be able to run the driver against a full-duplex interface
  2444.                   (with continuous CTS), such as another PC with a diagnostic
  2445.                   communications program.  The transmit interrupt uses the
  2446.                   same code as the MSR interrupt.
  2447.  
  2448.                   For initial testing of programs without actually running a
  2449.                   model railroad, you could use a 'wrap-plug' to partially
  2450.                   simulate the Märklin-Interface.  The RTS signal (raised by
  2451.                   the driver) is feeded back to CTS, so the driver is always
  2452.                   able transmit.
  2453.  
  2454.                   If also send and receive (generally pins 2 and 3) leads are
  2455.                   wrapped back, then the transmitted data is treated as S88
  2456.                   response.  This may cause
  2457.  
  2458.   Input flow control There is no form of input flow control allowed by the
  2459.                   Märklin-Interface: there is no way to signal the
  2460.                   Märklin-Interface to stop sending.  This will not be a
  2461.                   problem for the driver, since there is enough buffering and
  2462.                   CPU-power to process the low volume input in time.
  2463.  
  2464.   XON/XOFF flow control Not used.  This type of flow-control is not supported
  2465.                   by the Märklin-Interface, since the commands for the
  2466.                   Märklin-Interface may contain these characters!
  2467.  
  2468.                   OS/2: The standard COM[xx].SYS of OS/2 allows simulated
  2469.                   XON/XOFF.  A DosDevIOCtl-'XOFF' is issued to stop
  2470.                   transmitting buffered data when a 'stop'-command has to be
  2471.                   transmitted.  A DosDevIOCtl-'XON' is issued when a
  2472.                   subsequent 'go'-command is issued.
  2473.  
  2474.   Null stripping  The OS/2 COM[xx].SYS allows null stripping.  There are at
  2475.                   least 2 reasons for this feature not to be activated:
  2476.                   ■  Märklin S88 encoder's may respond with all bits zero
  2477.                   ■  Switch 256 is addressed as ASCII 0.
  2478.  
  2479.   Command parsing The driver does not interpret the data it sends to the
  2480.                   Märklin-Interface.  It means that it is completely the
  2481.                   responsibility of the mainline to ensure proper command
  2482.                   sequences.
  2483.  
  2484.                   Note: The driver does not send automatically a
  2485.                   switch-'relax' command (ASCII 32) after a switch command
  2486.                   (ASCII 33 or 34)!  You may write a shell for Märklin
  2487.                   command syntax checking.
  2488.  
  2489.  
  2490.  
  2491.   PROBLEMS WITH OS/2 COM[XX].SYS
  2492.  
  2493.   The Com-port driver of some versions of OS/2 for non-PS/2 machines
  2494.   (COM01.SYS) does have some known problems, such as:
  2495.  
  2496.   ■  READ and WRITE timout specifications cannot be changed from the built-in
  2497.      default of 1 minute.
  2498.  
  2499.   ───────────────────────────────────────────────────────────────────────────
  2500.                                             Appendix A.  MKLAPI Internals  37
  2501.  
  2502.   MKLAPI
  2503.   ───────────────────────────────────────────────────────────────────────────
  2504.   
  2505.   
  2506.   When encountering this kind of problems, I could recommend Gerry Rozema's
  2507.   replacement driver for AT-type machines (COM16540.SYS, or COM16550.SYS, as
  2508.   appropriate for your system's COM-port).  For OS/2 2.0 there is also a
  2509.   driver SIO.SYS by Ray Gwinn, that might be useful when having problems with
  2510.   the standard OS/2 2.0 drivers.
  2511.  
  2512.   These alternative drivers are available on Bulletin Boards such as
  2513.   PC-Square in The Netherlands (FIDO node 2:512/4, telephone 31.79.424107).
  2514.  
  2515.  
  2516.   OS/2 AND DOS DIFFERENCES
  2517.  
  2518.   Although all versions of this Märklin-driver offer a consistent application
  2519.   programming interface for communication with the Märklin-Interface, it is
  2520.   most likely that there will be differences between the programs using
  2521.   either of them.  Some of these differences might be:
  2522.  
  2523.   ■  When running in a multitasking environment, the program should give
  2524.      other tasks the chance to run (yield the processor).
  2525.      ∙  With OS/2 other tasks will get some control automatically
  2526.         (pre-emptive multi-tasking), but nevertheless the program should at
  2527.         least use DosSleep(0) when it does not need the processor for some
  2528.         time.
  2529.      ∙  DOS: apart from the built-in multitasking of the Märklin-driver which
  2530.         controls itself, you probably won't run other programs.  In that case
  2531.         you will not have to release the processor.
  2532.      ∙  When running a DOS-program under another multitasker (Windows,
  2533.         Desqview), periodic calls of mklsleep() are recommended.
  2534.  
  2535.   ■  The OS/2 driver makes use of the standard multitasking (multithreading)
  2536.      facilities.  Therefore any program using this driver should specify /MT
  2537.      for MicroSoft C-compiler 6.00a.  The different include-search might be
  2538.      indicated with a compiler option (-I for most C-compilers).
  2539.  
  2540.      The DOS driver should use the normal include directory.
  2541.  
  2542.   ■  The OS/2 driver requires the LARGE memory model compiler options and use
  2543.      the LLIBCMT library for LINK (automatic with /MT).  The DOS-version is
  2544.      for either the SMALL (/AS) or LARGE memory model (/AL), use the
  2545.      respectively the SLIBCE or LLIBCE library with LINK.
  2546.  
  2547.   ■  The standard OS/2-driver (COM[xx].SYS) will not accept new output data
  2548.      in stop-state, but will transmit possibly retained data (from before
  2549.      mklstop) after a call to 'mklgo'.  Some alternative drivers (such as
  2550.      SIO.COM) do accept new data from mklputc, but keep it internally
  2551.      buffered.  No more data is accepted when the buffer is full.  After
  2552.      mklgo() all buffered data, old and new, will be transmitted.
  2553.  
  2554.      The DOS-drivers refuse all new output data in stop-state.
  2555.  
  2556.   ■  It is an absolute must, that the Märklin-driver under DOS is terminated
  2557.      with a call to mklclose() to de-activate the interrupts for com-port and
  2558.      timer.  Therefore it is recommended to use a routine to intercept Ctrl-C
  2559.      or Ctrl-Break actions from the keyboard.
  2560.  
  2561.  
  2562.   ───────────────────────────────────────────────────────────────────────────
  2563.                                             Appendix A.  MKLAPI Internals  38
  2564.  
  2565.   MKLAPI
  2566.   ───────────────────────────────────────────────────────────────────────────
  2567.   
  2568.   
  2569.      Under OS/2 this attitude is recommended, but not an absolute must.
  2570.  
  2571.      In both cases it is recommended to direct the Ctrl-C signal to a
  2572.      controlled finish of your railroad control program: you probably do not
  2573.      want to terminate your program with uncontrolled running trains!
  2574.  
  2575.   ■  The display of information about the state of your railroad on the
  2576.      computer screen will probably use different techniques, such as the way
  2577.      cursor and color will be used:
  2578.      1. OS/2: Presentation Manager (graphics) or VIO routines.
  2579.      2. DOS: Windows (graphics)
  2580.      3. ANSI escape-sequences (compatible between OS/2 and DOS)
  2581.  
  2582.      The sample program you'll receive after registration is a single source
  2583.      for environments 1 and 3.  My own programs are primarily for OS/2 and I
  2584.      prefer to use the OS/2 facilities and those of the Program Development
  2585.      Toolkit as good as possible.  For instance I use VIO-routines for color
  2586.      and cursor manipulation.
  2587.  
  2588.      To be able to run my sample program under DOS, I included some extra
  2589.      routines in the header-file.  These routines translate color and cursor
  2590.      manipulations with OS/2 VIO-calls into equivalent ANSI escape sequences.
  2591.      When ANSI is active under DOS (with DEVICE=[path]\ANSI.SYS in
  2592.      CONFIG.SYS), the visual effects are the same as with the OS/2 version.
  2593.  
  2594.   When there is no possibility to use the same code for OS/2 and DOS, you
  2595.   might consider using a compiler variable (with the -D compiler option) to
  2596.   distinguish which pieces of codes are OS/2 or DOS specific.  See for an
  2597.   example the MAKE-files in the MKLAPI package.
  2598.  
  2599.  
  2600.  
  2601.  
  2602.  
  2603.  
  2604.  
  2605.  
  2606.  
  2607.  
  2608.  
  2609.  
  2610.  
  2611.  
  2612.  
  2613.  
  2614.  
  2615.  
  2616.  
  2617.  
  2618.  
  2619.  
  2620.  
  2621.  
  2622.  
  2623.  
  2624.  
  2625.   ───────────────────────────────────────────────────────────────────────────
  2626.                                             Appendix A.  MKLAPI Internals  39
  2627.  
  2628.   MKLAPI
  2629.   ───────────────────────────────────────────────────────────────────────────
  2630.   
  2631.   
  2632.   APPENDIX B.  TRACE FACILITY
  2633.  
  2634.  
  2635.  
  2636.   TRACE RECORDS
  2637.  
  2638.   The trace facility produces the following records (8 bytes each):
  2639.  
  2640.  
  2641.    long int timestamp;  /* value of mkltime */
  2642.    int  fl:1,           /* flag: 0=output, 1=input */
  2643.         nn:7,           /* (in start-of-trace record) trace source */
  2644.                         /* MKLAPI: DOS = 1; OS/2 1.x = 2; OS/2 2.x = 3 */
  2645.         sw:8;           /* S88 box number on input */
  2646.    char c1,             /* first character */
  2647.         c2;             /* second character */
  2648.  
  2649.   The first record after starting a trace contains 0xFF as first and second
  2650.   character.
  2651.  
  2652.  
  2653.   SAMPLE
  2654.  
  2655.   The output of the trace formatting program MKLTRFMT will look like:
  2656.  
  2657.  
  2658.         time    I/O  cmd  data  description
  2659.    ------------ ---  ---  ----  --------------------------------------
  2660.          45.050                 Start of trace (MKLAPI OS/2 1.x)
  2661.          +0.045  O    1A    13  Loc 19  speed 10  Funktion=ON
  2662.          +0.350  O    22    3F  switchpoint 63: branch
  2663.          +0.760  O    20        switchpoint release
  2664.          +1.850  O    C0        read S88's with reset
  2665.          +4.850  O    82        read S88 1 t/m 2
  2666.          +4.881  I        1801  S88  1 ON=4,5,16
  2667.          +4.881  I        090E  S88  2 ON=,8,13,14,15
  2668.          +5.000  O    61        STOP
  2669.  
  2670.   This is not a complete trace, just some parts to show the essentials.
  2671.  
  2672.   MKLTRFMT.EXE is a 'family mode' application: it will run under OS/2 and
  2673.   DOS.  No parameters are required, but you may specify the input filename
  2674.   [including path] if your trace is in another directory or named other than
  2675.   MKLAPI.TRC, which is the default (output filename of MKLAPI).
  2676.  
  2677.   MKLTRFMT writes the output to 'stdout', which is normally the computer
  2678.   display.  But the output may be redirected to your printer or to a file.
  2679.   So you could use for example the command:
  2680.  
  2681.     MKLTRFMT >TRACE.FMT
  2682.  
  2683.   so that you could look afterwards with a text editor or file browse utility
  2684. | in TRACE.FMT for the formatted trace.
  2685.  
  2686.  
  2687.  
  2688.   ───────────────────────────────────────────────────────────────────────────
  2689.                                               Appendix B.  Trace facility  40
  2690.  
  2691.   MKLAPI
  2692.   ───────────────────────────────────────────────────────────────────────────
  2693.   
  2694.   
  2695. | APPENDIX C.  MäRKLIN-INTERFACE PECULIARITIES
  2696.  
  2697. | When writing a model railroad control program (with or without this
  2698. | driver), you should be aware of some peculiarities, which are not very well
  2699. | (or not at all) documented by Märklin.  With experiments during development
  2700. | of MKLAPI I have found for example:
  2701.  
  2702. | ■  Sending 2 consecutive change-direction commands to the same loc does not
  2703. |    put the loc back in the original direction.  A zero-speed command
  2704. |    between them is a good circumvention.
  2705.  
  2706. | ■  When the Märklin-Interface is in 'stop'-state:
  2707. |    ∙  Permanent blocking (having to push the 'go'-button on the Märklin
  2708. |       Central Control)  does occur only with commands to train-decoders and
  2709. |       switch-point or light decoders (K83 or K84).
  2710. |    ∙  Reading Märklin S88 encoders (polling) may continue.  But since the
  2711. |       changes are not sent from the control-box to the Märklin-Interface,
  2712. |       it is not very useful.
  2713.  
  2714.  
  2715.  
  2716.  
  2717.  
  2718.  
  2719.  
  2720.  
  2721.  
  2722.  
  2723.  
  2724.  
  2725.  
  2726.  
  2727.  
  2728.  
  2729.  
  2730.  
  2731.  
  2732.  
  2733.  
  2734.  
  2735.  
  2736.  
  2737.  
  2738.  
  2739.  
  2740.  
  2741.  
  2742.  
  2743.  
  2744.  
  2745.  
  2746.  
  2747.  
  2748.  
  2749.  
  2750.  
  2751.   ───────────────────────────────────────────────────────────────────────────
  2752.                              Appendix C.  Märklin-Interface peculiarities  41
  2753.  
  2754.   MKLAPI
  2755.   ───────────────────────────────────────────────────────────────────────────
  2756.   
  2757.   
  2758.   APPENDIX D.  SUMMARY OF CHANGES
  2759.  
  2760.   0.7   First beta release: June 1992
  2761.  
  2762.   0.8   released: October 1992
  2763.         ■  The time-base value in mkltime has been changed from 55 msec to 1
  2764.            msec!(updating of mkltime still on timer-tick basis: once per 55
  2765.            msecs in DOS, once per 31.25 msecs in OS/2).
  2766.         ■  DOS: High precision timer routine added: mklmsecs().  This gives
  2767.            the period since line to opening of communication with
  2768.            Märklin-Interface  with 1 msec accuracy.
  2769.         ■  OS/2: Trace facility added (see also "Appendix B.  Trace facility"
  2770.            on page 40), start and stop of trace via procedure call
  2771.            mkltrace().  Output to and input from the Märklin-Interface is
  2772.            traced.  A trace-file formatting utility (MKLTRFMT.EXE) is added
  2773.            to package.  I have tried to add this trace facility also in the
  2774.            DOS driver, but I did not cucceed so far.  It is rather
  2775.            complicated to use DOS facilities during interrupt handling
  2776.            (tracing must be located in the com-port and timer interrupt
  2777.            routines).
  2778.         ■  A procedure 'mklsleep' added to make your DOS-program 'friendly'
  2779.            for some popular multitasking environments (such DOS-box of OS/2,
  2780.            Desqview, Windows).
  2781.         ■  DOS: mklflush times out after 3 seconds when transmit buffer could
  2782.            not be flushed.
  2783.         ■  Some bugs fixed:
  2784.            ∙  mklflush() of OS/2 version watched the INput in stead of OUTput
  2785.               queue.
  2786.            ∙  DOS: DTR and RTS now turned off before finishing program.
  2787.  
  2788.   0.9   released: March 1993
  2789.         ■  A 32-bits driver for OS/2 2.0+ (MKLAPI3.OBJ) has been added, with
  2790.            same functionality as MKLAPI2, including the new features below!
  2791.         ■  'MKLAPI' now also useable by programs translated with the
  2792.            MicroSoft QuickBASIC compiler 4.5.  Since QuickBASIC does not
  2793.            allow underscores in names, all externally used names have been
  2794.            changed, for example: mklopen() is now called mklopen().  The
  2795.            C-language calling convention must be specified in the source (see
  2796.            MKLAPI.INC), and the file LMKLAPI.OBJ should be used with LINK.
  2797.            All function specifications have been changed, and additions made
  2798.            for program development with MicroSoft QuickBASIC compiler 4.5.
  2799.         ■  mkltime() is not anymore an external variable, but a function
  2800.            returning the value of the time, expressed in milliseconds, but
  2801.            with the precision of the timer tick.
  2802.         ■  mklmsecs() now also a function returning the time, but in exact
  2803.            milliseconds (DOS only).
  2804.         ■  With the OS/2 drivers, the transmissions in STOP-state (after
  2805.            mklstop) may now be buffered in stead of discarded (until buffer
  2806.            full, then discarded).  This depends on the COM.SYS device
  2807.            drivers, or replacements thereof.
  2808.         ■  After the first mklstop subsequent calls of mklstop are ignored
  2809.            and nothing sent to the Märklin-Interface until mklgo has been
  2810.            called.
  2811.         ■  mklstop() and mklgo() now give a returncode (0 = OK, otherwise a
  2812.            transmission problem exists).
  2813.  
  2814.   ───────────────────────────────────────────────────────────────────────────
  2815.                                           Appendix D.  Summary of changes  42
  2816.  
  2817.   MKLAPI
  2818.   ───────────────────────────────────────────────────────────────────────────
  2819.   
  2820.   
  2821.         ■  Simple Switchpoint test program (incl c-source) added to MKLAPI
  2822.            package.
  2823.         ■  Added counters for and a function mklstats() for statistical
  2824.            purposes and debugging.
  2825.         ■  Polling optimised: a single 'reset after read S88' (192) is issued
  2826.            after mklpoll() and mklgo(), subsequently only 'read group of n
  2827.            S88s' (128+n) commands are sent periodically (previously both
  2828.            commands were sent after each interval).
  2829.  
  2830.   1.0   released: May 1993
  2831.         ■  Names and references to 'MARKLIN' renamed to MKLAPI, where the
  2832.            driver is meant (and not Märklin-components).  Include-files and
  2833.            sources that include header files should be changed.
  2834.         ■  DOS-drivers now take RS232 port addresses from the BIOS data-area,
  2835.            and performs a simple check if the port is not already in use.
  2836.         ■  Sound support added to DOS-drivers, and the function made callable
  2837.            by mainline.  Warning signals of OS/2- and DOS-drivers
  2838.            'harmonised'.
  2839.         ■  Polling and storage of S88 bit-settings changed to get better
  2840.            operation for all types of switches.
  2841.         ■  mklstop() and mklgo() made more reliable.
  2842.         ■  mklsleep() accepts now specification of an interval (pause) time
  2843.         ■  mklmsecs(), mklsound() and mklsleep() functions now present in
  2844.            both OS/2 and DOS versions for more compatibility between OS/2 and
  2845.            DOS versions of programs that make use of the MKLAPI-driver.
  2846.  
  2847.  
  2848.  
  2849.  
  2850.  
  2851.  
  2852.  
  2853.  
  2854.  
  2855.  
  2856.  
  2857.  
  2858.  
  2859.  
  2860.  
  2861.  
  2862.  
  2863.  
  2864.  
  2865.  
  2866.  
  2867.  
  2868.  
  2869.  
  2870.  
  2871.  
  2872.  
  2873.  
  2874.  
  2875.  
  2876.  
  2877.   ───────────────────────────────────────────────────────────────────────────
  2878.                                           Appendix D.  Summary of changes  43